10084047dSAppaRao Puli /* 20084047dSAppaRao Puli // Copyright (c) 2018 Intel Corporation 30084047dSAppaRao Puli // 40084047dSAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License"); 50084047dSAppaRao Puli // you may not use this file except in compliance with the License. 60084047dSAppaRao Puli // You may obtain a copy of the License at 70084047dSAppaRao Puli // 80084047dSAppaRao Puli // http://www.apache.org/licenses/LICENSE-2.0 90084047dSAppaRao Puli // 100084047dSAppaRao Puli // Unless required by applicable law or agreed to in writing, software 110084047dSAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS, 120084047dSAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130084047dSAppaRao Puli // See the License for the specific language governing permissions and 140084047dSAppaRao Puli // limitations under the License. 150084047dSAppaRao Puli */ 160084047dSAppaRao Puli #include <fstream> 170084047dSAppaRao Puli #include <regex> 1890f2da3fSRichard Marian Thomaiyar #include <boost/asio/spawn.hpp> 190084047dSAppaRao Puli #include "srvcfg_manager.hpp" 200084047dSAppaRao Puli 21*33816cf9SRichard Marian Thomaiyar extern std::unique_ptr<boost::asio::steady_timer> timer; 220084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>> 230084047dSAppaRao Puli srvMgrObjects; 2490f2da3fSRichard Marian Thomaiyar static bool updateInProgress = false; 250084047dSAppaRao Puli 260084047dSAppaRao Puli namespace phosphor 270084047dSAppaRao Puli { 280084047dSAppaRao Puli namespace service 290084047dSAppaRao Puli { 300084047dSAppaRao Puli 310084047dSAppaRao Puli static constexpr const char *overrideConfFileName = "override.conf"; 320084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds 330084047dSAppaRao Puli 340084047dSAppaRao Puli static constexpr const char *systemd1UnitBasePath = 350084047dSAppaRao Puli "/org/freedesktop/systemd1/unit/"; 360084047dSAppaRao Puli static constexpr const char *systemdOverrideUnitBasePath = 370084047dSAppaRao Puli "/etc/systemd/system/"; 380084047dSAppaRao Puli 3990f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateSocketProperties( 4090f2da3fSRichard Marian Thomaiyar const boost::container::flat_map<std::string, VariantType> &propertyMap) 410084047dSAppaRao Puli { 4290f2da3fSRichard Marian Thomaiyar auto listenIt = propertyMap.find("Listen"); 4390f2da3fSRichard Marian Thomaiyar if (listenIt != propertyMap.end()) 440084047dSAppaRao Puli { 4590f2da3fSRichard Marian Thomaiyar auto listenVal = 4690f2da3fSRichard Marian Thomaiyar std::get<std::vector<std::tuple<std::string, std::string>>>( 4790f2da3fSRichard Marian Thomaiyar listenIt->second); 4890f2da3fSRichard Marian Thomaiyar if (listenVal.size()) 490084047dSAppaRao Puli { 500084047dSAppaRao Puli protocol = std::get<0>(listenVal[0]); 510084047dSAppaRao Puli std::string port = std::get<1>(listenVal[0]); 520084047dSAppaRao Puli auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1), 530084047dSAppaRao Puli nullptr, 10); 540084047dSAppaRao Puli if (tmp > std::numeric_limits<uint16_t>::max()) 550084047dSAppaRao Puli { 560084047dSAppaRao Puli throw std::out_of_range("Out of range"); 570084047dSAppaRao Puli } 580084047dSAppaRao Puli portNum = tmp; 5990f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 6090f2da3fSRichard Marian Thomaiyar { 6190f2da3fSRichard Marian Thomaiyar internalSet = true; 6290f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropPort, portNum); 6390f2da3fSRichard Marian Thomaiyar internalSet = false; 6490f2da3fSRichard Marian Thomaiyar } 6590f2da3fSRichard Marian Thomaiyar } 6690f2da3fSRichard Marian Thomaiyar } 6790f2da3fSRichard Marian Thomaiyar } 6890f2da3fSRichard Marian Thomaiyar 6990f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateServiceProperties( 7090f2da3fSRichard Marian Thomaiyar const boost::container::flat_map<std::string, VariantType> &propertyMap) 7190f2da3fSRichard Marian Thomaiyar { 7290f2da3fSRichard Marian Thomaiyar auto stateIt = propertyMap.find("UnitFileState"); 7390f2da3fSRichard Marian Thomaiyar if (stateIt != propertyMap.end()) 7490f2da3fSRichard Marian Thomaiyar { 7590f2da3fSRichard Marian Thomaiyar stateValue = std::get<std::string>(stateIt->second); 7690f2da3fSRichard Marian Thomaiyar unitEnabledState = unitMaskedState = false; 7790f2da3fSRichard Marian Thomaiyar if (stateValue == stateMasked) 7890f2da3fSRichard Marian Thomaiyar { 7990f2da3fSRichard Marian Thomaiyar unitMaskedState = true; 8090f2da3fSRichard Marian Thomaiyar } 8190f2da3fSRichard Marian Thomaiyar else if (stateValue == stateEnabled) 8290f2da3fSRichard Marian Thomaiyar { 8390f2da3fSRichard Marian Thomaiyar unitEnabledState = true; 8490f2da3fSRichard Marian Thomaiyar } 8590f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 8690f2da3fSRichard Marian Thomaiyar { 8790f2da3fSRichard Marian Thomaiyar internalSet = true; 8890f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropMasked, unitMaskedState); 8990f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropEnabled, unitEnabledState); 9090f2da3fSRichard Marian Thomaiyar internalSet = false; 9190f2da3fSRichard Marian Thomaiyar } 9290f2da3fSRichard Marian Thomaiyar } 9390f2da3fSRichard Marian Thomaiyar auto subStateIt = propertyMap.find("SubState"); 9490f2da3fSRichard Marian Thomaiyar if (subStateIt != propertyMap.end()) 9590f2da3fSRichard Marian Thomaiyar { 9690f2da3fSRichard Marian Thomaiyar subStateValue = std::get<std::string>(subStateIt->second); 9790f2da3fSRichard Marian Thomaiyar if (subStateValue == subStateRunning) 9890f2da3fSRichard Marian Thomaiyar { 9990f2da3fSRichard Marian Thomaiyar unitRunningState = true; 10090f2da3fSRichard Marian Thomaiyar } 10190f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 10290f2da3fSRichard Marian Thomaiyar { 10390f2da3fSRichard Marian Thomaiyar internalSet = true; 10490f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropRunning, unitRunningState); 10590f2da3fSRichard Marian Thomaiyar internalSet = false; 10690f2da3fSRichard Marian Thomaiyar } 10790f2da3fSRichard Marian Thomaiyar } 10890f2da3fSRichard Marian Thomaiyar } 10990f2da3fSRichard Marian Thomaiyar 11090f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties() 11190f2da3fSRichard Marian Thomaiyar { 11290f2da3fSRichard Marian Thomaiyar conn->async_method_call( 11390f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 11490f2da3fSRichard Marian Thomaiyar const boost::container::flat_map<std::string, VariantType> 11590f2da3fSRichard Marian Thomaiyar &propertyMap) { 11690f2da3fSRichard Marian Thomaiyar if (ec) 11790f2da3fSRichard Marian Thomaiyar { 11890f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 11990f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to service unit " 12090f2da3fSRichard Marian Thomaiyar "properties"); 12190f2da3fSRichard Marian Thomaiyar return; 12290f2da3fSRichard Marian Thomaiyar } 12390f2da3fSRichard Marian Thomaiyar try 12490f2da3fSRichard Marian Thomaiyar { 12590f2da3fSRichard Marian Thomaiyar updateServiceProperties(propertyMap); 12690f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 12790f2da3fSRichard Marian Thomaiyar { 12890f2da3fSRichard Marian Thomaiyar conn->async_method_call( 12990f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 13090f2da3fSRichard Marian Thomaiyar const boost::container::flat_map< 13190f2da3fSRichard Marian Thomaiyar std::string, VariantType> &propertyMap) { 13290f2da3fSRichard Marian Thomaiyar if (ec) 13390f2da3fSRichard Marian Thomaiyar { 13490f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 13590f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 13690f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to get " 13790f2da3fSRichard Marian Thomaiyar "all property"); 13890f2da3fSRichard Marian Thomaiyar return; 13990f2da3fSRichard Marian Thomaiyar } 14090f2da3fSRichard Marian Thomaiyar try 14190f2da3fSRichard Marian Thomaiyar { 14290f2da3fSRichard Marian Thomaiyar updateSocketProperties(propertyMap); 14390f2da3fSRichard Marian Thomaiyar if (!iface) 14490f2da3fSRichard Marian Thomaiyar { 14590f2da3fSRichard Marian Thomaiyar registerProperties(); 14690f2da3fSRichard Marian Thomaiyar } 14790f2da3fSRichard Marian Thomaiyar } 14890f2da3fSRichard Marian Thomaiyar catch (const std::exception &e) 14990f2da3fSRichard Marian Thomaiyar { 15090f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 15190f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 15290f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 15390f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("WHAT=%s", 15490f2da3fSRichard Marian Thomaiyar e.what())); 15590f2da3fSRichard Marian Thomaiyar return; 15690f2da3fSRichard Marian Thomaiyar } 15790f2da3fSRichard Marian Thomaiyar }, 15890f2da3fSRichard Marian Thomaiyar sysdService, socketObjectPath, dBusPropIntf, 15990f2da3fSRichard Marian Thomaiyar dBusGetAllMethod, sysdSocketIntf); 16090f2da3fSRichard Marian Thomaiyar } 16190f2da3fSRichard Marian Thomaiyar else if (!iface) 16290f2da3fSRichard Marian Thomaiyar { 16390f2da3fSRichard Marian Thomaiyar registerProperties(); 16490f2da3fSRichard Marian Thomaiyar } 1650084047dSAppaRao Puli } 1660084047dSAppaRao Puli catch (const std::exception &e) 1670084047dSAppaRao Puli { 1680084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 16990f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 1700084047dSAppaRao Puli phosphor::logging::entry("WHAT=%s", e.what())); 1710084047dSAppaRao Puli return; 1720084047dSAppaRao Puli } 1730084047dSAppaRao Puli }, 17490f2da3fSRichard Marian Thomaiyar sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod, 17590f2da3fSRichard Marian Thomaiyar sysdUnitIntf); 1760084047dSAppaRao Puli return; 1770084047dSAppaRao Puli } 1780084047dSAppaRao Puli 17990f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf() 1800084047dSAppaRao Puli { 18190f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 1820084047dSAppaRao Puli { 18390f2da3fSRichard Marian Thomaiyar std::string socketUnitName(instantiatedUnitName + ".socket"); 1840084047dSAppaRao Puli /// Check override socket directory exist, if not create it. 1850084047dSAppaRao Puli std::experimental::filesystem::path ovrUnitFileDir( 1860084047dSAppaRao Puli systemdOverrideUnitBasePath); 1870084047dSAppaRao Puli ovrUnitFileDir += socketUnitName; 1880084047dSAppaRao Puli ovrUnitFileDir += ".d"; 1890084047dSAppaRao Puli if (!std::experimental::filesystem::exists(ovrUnitFileDir)) 1900084047dSAppaRao Puli { 19190f2da3fSRichard Marian Thomaiyar if (!std::experimental::filesystem::create_directories( 19290f2da3fSRichard Marian Thomaiyar ovrUnitFileDir)) 1930084047dSAppaRao Puli { 1940084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1950084047dSAppaRao Puli "Unable to create the directory.", 1960084047dSAppaRao Puli phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str())); 19790f2da3fSRichard Marian Thomaiyar phosphor::logging::elog<sdbusplus::xyz::openbmc_project:: 19890f2da3fSRichard Marian Thomaiyar Common::Error::InternalFailure>(); 19990f2da3fSRichard Marian Thomaiyar } 20090f2da3fSRichard Marian Thomaiyar } 20190f2da3fSRichard Marian Thomaiyar overrideConfDir = std::string(ovrUnitFileDir); 2020084047dSAppaRao Puli } 2030084047dSAppaRao Puli } 2040084047dSAppaRao Puli 20590f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig( 20690f2da3fSRichard Marian Thomaiyar sdbusplus::asio::object_server &srv_, 20790f2da3fSRichard Marian Thomaiyar std::shared_ptr<sdbusplus::asio::connection> &conn_, 20890f2da3fSRichard Marian Thomaiyar const std::string &objPath_, const std::string &baseUnitName_, 20990f2da3fSRichard Marian Thomaiyar const std::string &instanceName_, const std::string &serviceObjPath_, 21090f2da3fSRichard Marian Thomaiyar const std::string &socketObjPath_) : 21190f2da3fSRichard Marian Thomaiyar server(srv_), 21290f2da3fSRichard Marian Thomaiyar conn(conn_), objPath(objPath_), baseUnitName(baseUnitName_), 21390f2da3fSRichard Marian Thomaiyar instanceName(instanceName_), serviceObjectPath(serviceObjPath_), 21490f2da3fSRichard Marian Thomaiyar socketObjectPath(socketObjPath_) 21590f2da3fSRichard Marian Thomaiyar { 21690f2da3fSRichard Marian Thomaiyar instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@"); 2170084047dSAppaRao Puli updatedFlag = 0; 21890f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 2190084047dSAppaRao Puli return; 2200084047dSAppaRao Puli } 2210084047dSAppaRao Puli 22290f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName() 2230084047dSAppaRao Puli { 22490f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".socket"; 225e55cfd6eSAppaRao Puli } 226e55cfd6eSAppaRao Puli 22790f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName() 22890f2da3fSRichard Marian Thomaiyar { 22990f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".service"; 23090f2da3fSRichard Marian Thomaiyar } 23190f2da3fSRichard Marian Thomaiyar 23290f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut() 23390f2da3fSRichard Marian Thomaiyar { 23490f2da3fSRichard Marian Thomaiyar // return true if state is masked & no request to update the maskedState 23590f2da3fSRichard Marian Thomaiyar return ( 23690f2da3fSRichard Marian Thomaiyar stateValue == "masked" && 23790f2da3fSRichard Marian Thomaiyar !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState)))); 23890f2da3fSRichard Marian Thomaiyar } 23990f2da3fSRichard Marian Thomaiyar 24090f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield) 24190f2da3fSRichard Marian Thomaiyar { 24290f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 24390f2da3fSRichard Marian Thomaiyar { 24490f2da3fSRichard Marian Thomaiyar // No updates / masked - Just return. 24590f2da3fSRichard Marian Thomaiyar return; 24690f2da3fSRichard Marian Thomaiyar } 2470084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::INFO>( 2480084047dSAppaRao Puli "Applying new settings.", 2490084047dSAppaRao Puli phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 25090f2da3fSRichard Marian Thomaiyar if (subStateValue == "running") 2510084047dSAppaRao Puli { 25290f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 25390f2da3fSRichard Marian Thomaiyar { 25490f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit); 25590f2da3fSRichard Marian Thomaiyar } 25690f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit); 25790f2da3fSRichard Marian Thomaiyar } 25890f2da3fSRichard Marian Thomaiyar 25990f2da3fSRichard Marian Thomaiyar if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port))) 26090f2da3fSRichard Marian Thomaiyar { 26190f2da3fSRichard Marian Thomaiyar createSocketOverrideConf(); 2620084047dSAppaRao Puli // Create override config file and write data. 26390f2da3fSRichard Marian Thomaiyar std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName}; 2640084047dSAppaRao Puli std::string tmpFile{ovrCfgFile + "_tmp"}; 2650084047dSAppaRao Puli std::ofstream cfgFile(tmpFile, std::ios::out); 2660084047dSAppaRao Puli if (!cfgFile.good()) 2670084047dSAppaRao Puli { 2680084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2690084047dSAppaRao Puli "Failed to open override.conf_tmp file"); 2700084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2710084047dSAppaRao Puli Error::InternalFailure>(); 2720084047dSAppaRao Puli } 2730084047dSAppaRao Puli 2740084047dSAppaRao Puli // Write the socket header 2750084047dSAppaRao Puli cfgFile << "[Socket]\n"; 2760084047dSAppaRao Puli // Listen 2770084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" 2780084047dSAppaRao Puli << "\n"; 2790084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" << portNum << "\n"; 2800084047dSAppaRao Puli cfgFile.close(); 2810084047dSAppaRao Puli 2820084047dSAppaRao Puli if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0) 2830084047dSAppaRao Puli { 2840084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2850084047dSAppaRao Puli "Failed to rename tmp file as override.conf"); 2860084047dSAppaRao Puli std::remove(tmpFile.c_str()); 2870084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2880084047dSAppaRao Puli Error::InternalFailure>(); 2890084047dSAppaRao Puli } 290e55cfd6eSAppaRao Puli } 2910084047dSAppaRao Puli 29290f2da3fSRichard Marian Thomaiyar if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 29390f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)))) 294e55cfd6eSAppaRao Puli { 29590f2da3fSRichard Marian Thomaiyar std::vector<std::string> unitFiles; 29690f2da3fSRichard Marian Thomaiyar if (socketObjectPath.empty()) 29790f2da3fSRichard Marian Thomaiyar { 29890f2da3fSRichard Marian Thomaiyar unitFiles = {getServiceUnitName()}; 299e55cfd6eSAppaRao Puli } 30090f2da3fSRichard Marian Thomaiyar else 301e55cfd6eSAppaRao Puli { 30290f2da3fSRichard Marian Thomaiyar unitFiles = {getSocketUnitName(), getServiceUnitName()}; 30390f2da3fSRichard Marian Thomaiyar } 30490f2da3fSRichard Marian Thomaiyar systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue, 30590f2da3fSRichard Marian Thomaiyar unitMaskedState, unitEnabledState); 30690f2da3fSRichard Marian Thomaiyar } 30790f2da3fSRichard Marian Thomaiyar return; 30890f2da3fSRichard Marian Thomaiyar } 30990f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield) 31090f2da3fSRichard Marian Thomaiyar { 31190f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 31290f2da3fSRichard Marian Thomaiyar { 31390f2da3fSRichard Marian Thomaiyar // No updates. Just return. 31490f2da3fSRichard Marian Thomaiyar return; 3150084047dSAppaRao Puli } 3160084047dSAppaRao Puli 31790f2da3fSRichard Marian Thomaiyar if (unitRunningState) 3180084047dSAppaRao Puli { 31990f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 32090f2da3fSRichard Marian Thomaiyar { 32190f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), 32290f2da3fSRichard Marian Thomaiyar sysdRestartUnit); 3230084047dSAppaRao Puli } 32490f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit); 3250084047dSAppaRao Puli } 3260084047dSAppaRao Puli 3270084047dSAppaRao Puli // Reset the flag 3280084047dSAppaRao Puli updatedFlag = 0; 3290084047dSAppaRao Puli 33090f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::INFO>( 33190f2da3fSRichard Marian Thomaiyar "Applied new settings", 33290f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 3330084047dSAppaRao Puli 33490f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 3350084047dSAppaRao Puli return; 3360084047dSAppaRao Puli } 3370084047dSAppaRao Puli 3380084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer() 3390084047dSAppaRao Puli { 340*33816cf9SRichard Marian Thomaiyar timer->expires_after(std::chrono::seconds(restartTimeout)); 3410084047dSAppaRao Puli timer->async_wait([this](const boost::system::error_code &ec) { 3420084047dSAppaRao Puli if (ec == boost::asio::error::operation_aborted) 3430084047dSAppaRao Puli { 3440084047dSAppaRao Puli // Timer reset. 3450084047dSAppaRao Puli return; 3460084047dSAppaRao Puli } 3470084047dSAppaRao Puli else if (ec) 3480084047dSAppaRao Puli { 3490084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 3500084047dSAppaRao Puli "async wait error."); 3510084047dSAppaRao Puli return; 3520084047dSAppaRao Puli } 35390f2da3fSRichard Marian Thomaiyar updateInProgress = true; 35490f2da3fSRichard Marian Thomaiyar boost::asio::spawn(conn->get_io_context(), 35590f2da3fSRichard Marian Thomaiyar [this](boost::asio::yield_context yield) { 35690f2da3fSRichard Marian Thomaiyar // Stop and apply configuration for all objects 3570084047dSAppaRao Puli for (auto &srvMgrObj : srvMgrObjects) 3580084047dSAppaRao Puli { 3590084047dSAppaRao Puli auto &srvObj = srvMgrObj.second; 3600084047dSAppaRao Puli if (srvObj->updatedFlag) 3610084047dSAppaRao Puli { 36290f2da3fSRichard Marian Thomaiyar srvObj->stopAndApplyUnitConfig(yield); 3630084047dSAppaRao Puli } 3640084047dSAppaRao Puli } 36590f2da3fSRichard Marian Thomaiyar // Do system reload 36690f2da3fSRichard Marian Thomaiyar systemdDaemonReload(conn, yield); 36790f2da3fSRichard Marian Thomaiyar // restart unit config. 36890f2da3fSRichard Marian Thomaiyar for (auto &srvMgrObj : srvMgrObjects) 36990f2da3fSRichard Marian Thomaiyar { 37090f2da3fSRichard Marian Thomaiyar auto &srvObj = srvMgrObj.second; 37190f2da3fSRichard Marian Thomaiyar if (srvObj->updatedFlag) 37290f2da3fSRichard Marian Thomaiyar { 37390f2da3fSRichard Marian Thomaiyar srvObj->restartUnitConfig(yield); 37490f2da3fSRichard Marian Thomaiyar } 37590f2da3fSRichard Marian Thomaiyar } 37690f2da3fSRichard Marian Thomaiyar updateInProgress = false; 37790f2da3fSRichard Marian Thomaiyar }); 3780084047dSAppaRao Puli }); 3790084047dSAppaRao Puli } 3800084047dSAppaRao Puli 3810084047dSAppaRao Puli void ServiceConfig::registerProperties() 3820084047dSAppaRao Puli { 38390f2da3fSRichard Marian Thomaiyar iface = server.add_interface(objPath, serviceConfigIntfName); 3840084047dSAppaRao Puli 38590f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 38690f2da3fSRichard Marian Thomaiyar { 3870084047dSAppaRao Puli iface->register_property( 38890f2da3fSRichard Marian Thomaiyar srvCfgPropPort, portNum, 38990f2da3fSRichard Marian Thomaiyar [this](const uint16_t &req, uint16_t &res) { 39090f2da3fSRichard Marian Thomaiyar if (!internalSet) 39190f2da3fSRichard Marian Thomaiyar { 3920084047dSAppaRao Puli if (req == res) 3930084047dSAppaRao Puli { 3940084047dSAppaRao Puli return 1; 3950084047dSAppaRao Puli } 39690f2da3fSRichard Marian Thomaiyar if (updateInProgress) 39790f2da3fSRichard Marian Thomaiyar { 39890f2da3fSRichard Marian Thomaiyar return 0; 39990f2da3fSRichard Marian Thomaiyar } 4000084047dSAppaRao Puli portNum = req; 40190f2da3fSRichard Marian Thomaiyar updatedFlag |= 40290f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::port)); 4030084047dSAppaRao Puli startServiceRestartTimer(); 40490f2da3fSRichard Marian Thomaiyar } 40590f2da3fSRichard Marian Thomaiyar res = req; 40690f2da3fSRichard Marian Thomaiyar return 1; 40790f2da3fSRichard Marian Thomaiyar }); 40890f2da3fSRichard Marian Thomaiyar } 40990f2da3fSRichard Marian Thomaiyar 41090f2da3fSRichard Marian Thomaiyar iface->register_property( 41190f2da3fSRichard Marian Thomaiyar srvCfgPropMasked, unitMaskedState, [this](const bool &req, bool &res) { 41290f2da3fSRichard Marian Thomaiyar if (!internalSet) 41390f2da3fSRichard Marian Thomaiyar { 41490f2da3fSRichard Marian Thomaiyar if (req == res) 41590f2da3fSRichard Marian Thomaiyar { 41690f2da3fSRichard Marian Thomaiyar return 1; 41790f2da3fSRichard Marian Thomaiyar } 41890f2da3fSRichard Marian Thomaiyar if (updateInProgress) 41990f2da3fSRichard Marian Thomaiyar { 42090f2da3fSRichard Marian Thomaiyar return 0; 42190f2da3fSRichard Marian Thomaiyar } 42290f2da3fSRichard Marian Thomaiyar unitMaskedState = req; 42390f2da3fSRichard Marian Thomaiyar unitEnabledState = !unitMaskedState; 42490f2da3fSRichard Marian Thomaiyar unitRunningState = !unitMaskedState; 42590f2da3fSRichard Marian Thomaiyar updatedFlag |= 42690f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 42790f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) | 42890f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 42990f2da3fSRichard Marian Thomaiyar internalSet = true; 43090f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropEnabled, unitEnabledState); 43190f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropRunning, unitRunningState); 43290f2da3fSRichard Marian Thomaiyar internalSet = false; 43390f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 43490f2da3fSRichard Marian Thomaiyar } 4350084047dSAppaRao Puli res = req; 4360084047dSAppaRao Puli return 1; 4370084047dSAppaRao Puli }); 4380084047dSAppaRao Puli 4390084047dSAppaRao Puli iface->register_property( 44090f2da3fSRichard Marian Thomaiyar srvCfgPropEnabled, unitEnabledState, 44190f2da3fSRichard Marian Thomaiyar [this](const bool &req, bool &res) { 44290f2da3fSRichard Marian Thomaiyar if (!internalSet) 44390f2da3fSRichard Marian Thomaiyar { 4440084047dSAppaRao Puli if (req == res) 4450084047dSAppaRao Puli { 4460084047dSAppaRao Puli return 1; 4470084047dSAppaRao Puli } 44890f2da3fSRichard Marian Thomaiyar if (updateInProgress) 4490084047dSAppaRao Puli { 45090f2da3fSRichard Marian Thomaiyar return 0; 4510084047dSAppaRao Puli } 45290f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 45390f2da3fSRichard Marian Thomaiyar { // block updating if masked 4540084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 4550084047dSAppaRao Puli "Invalid value specified"); 4560084047dSAppaRao Puli return -EINVAL; 4570084047dSAppaRao Puli } 45890f2da3fSRichard Marian Thomaiyar unitEnabledState = req; 45990f2da3fSRichard Marian Thomaiyar updatedFlag |= 46090f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)); 4610084047dSAppaRao Puli startServiceRestartTimer(); 46290f2da3fSRichard Marian Thomaiyar } 46390f2da3fSRichard Marian Thomaiyar res = req; 46490f2da3fSRichard Marian Thomaiyar return 1; 46590f2da3fSRichard Marian Thomaiyar }); 46690f2da3fSRichard Marian Thomaiyar 46790f2da3fSRichard Marian Thomaiyar iface->register_property( 46890f2da3fSRichard Marian Thomaiyar srvCfgPropRunning, unitRunningState, 46990f2da3fSRichard Marian Thomaiyar [this](const bool &req, bool &res) { 47090f2da3fSRichard Marian Thomaiyar if (!internalSet) 47190f2da3fSRichard Marian Thomaiyar { 47290f2da3fSRichard Marian Thomaiyar if (req == res) 47390f2da3fSRichard Marian Thomaiyar { 47490f2da3fSRichard Marian Thomaiyar return 1; 47590f2da3fSRichard Marian Thomaiyar } 47690f2da3fSRichard Marian Thomaiyar if (updateInProgress) 47790f2da3fSRichard Marian Thomaiyar { 47890f2da3fSRichard Marian Thomaiyar return 0; 47990f2da3fSRichard Marian Thomaiyar } 48090f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 48190f2da3fSRichard Marian Thomaiyar { // block updating if masked 48290f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 48390f2da3fSRichard Marian Thomaiyar "Invalid value specified"); 48490f2da3fSRichard Marian Thomaiyar return -EINVAL; 48590f2da3fSRichard Marian Thomaiyar } 48690f2da3fSRichard Marian Thomaiyar unitRunningState = req; 48790f2da3fSRichard Marian Thomaiyar updatedFlag |= 48890f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 48990f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 49090f2da3fSRichard Marian Thomaiyar } 4910084047dSAppaRao Puli res = req; 4920084047dSAppaRao Puli return 1; 4930084047dSAppaRao Puli }); 4940084047dSAppaRao Puli 4950084047dSAppaRao Puli iface->initialize(); 4960084047dSAppaRao Puli return; 4970084047dSAppaRao Puli } 4980084047dSAppaRao Puli 4990084047dSAppaRao Puli } // namespace service 5000084047dSAppaRao Puli } // namespace phosphor 501