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 */ 16*ee853eb2SAppaRao Puli #include "srvcfg_manager.hpp" 17*ee853eb2SAppaRao Puli 18*ee853eb2SAppaRao Puli #include <boost/asio/spawn.hpp> 19*ee853eb2SAppaRao Puli 200084047dSAppaRao Puli #include <fstream> 210084047dSAppaRao Puli #include <regex> 220084047dSAppaRao Puli 2333816cf9SRichard Marian Thomaiyar extern std::unique_ptr<boost::asio::steady_timer> timer; 240084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>> 250084047dSAppaRao Puli srvMgrObjects; 2690f2da3fSRichard Marian Thomaiyar static bool updateInProgress = false; 270084047dSAppaRao Puli 280084047dSAppaRao Puli namespace phosphor 290084047dSAppaRao Puli { 300084047dSAppaRao Puli namespace service 310084047dSAppaRao Puli { 320084047dSAppaRao Puli 330084047dSAppaRao Puli static constexpr const char* overrideConfFileName = "override.conf"; 340084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds 350084047dSAppaRao Puli 360084047dSAppaRao Puli static constexpr const char* systemd1UnitBasePath = 370084047dSAppaRao Puli "/org/freedesktop/systemd1/unit/"; 380084047dSAppaRao Puli static constexpr const char* systemdOverrideUnitBasePath = 390084047dSAppaRao Puli "/etc/systemd/system/"; 400084047dSAppaRao Puli 4190f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateSocketProperties( 4290f2da3fSRichard Marian Thomaiyar const boost::container::flat_map<std::string, VariantType>& propertyMap) 430084047dSAppaRao Puli { 4490f2da3fSRichard Marian Thomaiyar auto listenIt = propertyMap.find("Listen"); 4590f2da3fSRichard Marian Thomaiyar if (listenIt != propertyMap.end()) 460084047dSAppaRao Puli { 4790f2da3fSRichard Marian Thomaiyar auto listenVal = 4890f2da3fSRichard Marian Thomaiyar std::get<std::vector<std::tuple<std::string, std::string>>>( 4990f2da3fSRichard Marian Thomaiyar listenIt->second); 5090f2da3fSRichard Marian Thomaiyar if (listenVal.size()) 510084047dSAppaRao Puli { 520084047dSAppaRao Puli protocol = std::get<0>(listenVal[0]); 530084047dSAppaRao Puli std::string port = std::get<1>(listenVal[0]); 540084047dSAppaRao Puli auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1), 550084047dSAppaRao Puli nullptr, 10); 560084047dSAppaRao Puli if (tmp > std::numeric_limits<uint16_t>::max()) 570084047dSAppaRao Puli { 580084047dSAppaRao Puli throw std::out_of_range("Out of range"); 590084047dSAppaRao Puli } 600084047dSAppaRao Puli portNum = tmp; 6190f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 6290f2da3fSRichard Marian Thomaiyar { 6390f2da3fSRichard Marian Thomaiyar internalSet = true; 6490f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropPort, portNum); 6590f2da3fSRichard Marian Thomaiyar internalSet = false; 6690f2da3fSRichard Marian Thomaiyar } 6790f2da3fSRichard Marian Thomaiyar } 6890f2da3fSRichard Marian Thomaiyar } 6990f2da3fSRichard Marian Thomaiyar } 7090f2da3fSRichard Marian Thomaiyar 7190f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateServiceProperties( 7290f2da3fSRichard Marian Thomaiyar const boost::container::flat_map<std::string, VariantType>& propertyMap) 7390f2da3fSRichard Marian Thomaiyar { 7490f2da3fSRichard Marian Thomaiyar auto stateIt = propertyMap.find("UnitFileState"); 7590f2da3fSRichard Marian Thomaiyar if (stateIt != propertyMap.end()) 7690f2da3fSRichard Marian Thomaiyar { 7790f2da3fSRichard Marian Thomaiyar stateValue = std::get<std::string>(stateIt->second); 7890f2da3fSRichard Marian Thomaiyar unitEnabledState = unitMaskedState = false; 7990f2da3fSRichard Marian Thomaiyar if (stateValue == stateMasked) 8090f2da3fSRichard Marian Thomaiyar { 8190f2da3fSRichard Marian Thomaiyar unitMaskedState = true; 8290f2da3fSRichard Marian Thomaiyar } 8390f2da3fSRichard Marian Thomaiyar else if (stateValue == stateEnabled) 8490f2da3fSRichard Marian Thomaiyar { 8590f2da3fSRichard Marian Thomaiyar unitEnabledState = true; 8690f2da3fSRichard Marian Thomaiyar } 8790f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 8890f2da3fSRichard Marian Thomaiyar { 8990f2da3fSRichard Marian Thomaiyar internalSet = true; 9090f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropMasked, unitMaskedState); 9190f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropEnabled, unitEnabledState); 9290f2da3fSRichard Marian Thomaiyar internalSet = false; 9390f2da3fSRichard Marian Thomaiyar } 9490f2da3fSRichard Marian Thomaiyar } 9590f2da3fSRichard Marian Thomaiyar auto subStateIt = propertyMap.find("SubState"); 9690f2da3fSRichard Marian Thomaiyar if (subStateIt != propertyMap.end()) 9790f2da3fSRichard Marian Thomaiyar { 9890f2da3fSRichard Marian Thomaiyar subStateValue = std::get<std::string>(subStateIt->second); 9990f2da3fSRichard Marian Thomaiyar if (subStateValue == subStateRunning) 10090f2da3fSRichard Marian Thomaiyar { 10190f2da3fSRichard Marian Thomaiyar unitRunningState = true; 10290f2da3fSRichard Marian Thomaiyar } 10390f2da3fSRichard Marian Thomaiyar if (iface && iface->is_initialized()) 10490f2da3fSRichard Marian Thomaiyar { 10590f2da3fSRichard Marian Thomaiyar internalSet = true; 10690f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropRunning, unitRunningState); 10790f2da3fSRichard Marian Thomaiyar internalSet = false; 10890f2da3fSRichard Marian Thomaiyar } 10990f2da3fSRichard Marian Thomaiyar } 11090f2da3fSRichard Marian Thomaiyar } 11190f2da3fSRichard Marian Thomaiyar 11290f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties() 11390f2da3fSRichard Marian Thomaiyar { 11490f2da3fSRichard Marian Thomaiyar conn->async_method_call( 11590f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 116*ee853eb2SAppaRao Puli const boost::container::flat_map<std::string, VariantType>& 117*ee853eb2SAppaRao Puli propertyMap) { 11890f2da3fSRichard Marian Thomaiyar if (ec) 11990f2da3fSRichard Marian Thomaiyar { 12090f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 12190f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to service unit " 12290f2da3fSRichard Marian Thomaiyar "properties"); 12390f2da3fSRichard Marian Thomaiyar return; 12490f2da3fSRichard Marian Thomaiyar } 12590f2da3fSRichard Marian Thomaiyar try 12690f2da3fSRichard Marian Thomaiyar { 12790f2da3fSRichard Marian Thomaiyar updateServiceProperties(propertyMap); 12890f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 12990f2da3fSRichard Marian Thomaiyar { 13090f2da3fSRichard Marian Thomaiyar conn->async_method_call( 13190f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 13290f2da3fSRichard Marian Thomaiyar const boost::container::flat_map< 13390f2da3fSRichard Marian Thomaiyar std::string, VariantType>& propertyMap) { 13490f2da3fSRichard Marian Thomaiyar if (ec) 13590f2da3fSRichard Marian Thomaiyar { 13690f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 13790f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 13890f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to get " 13990f2da3fSRichard Marian Thomaiyar "all property"); 14090f2da3fSRichard Marian Thomaiyar return; 14190f2da3fSRichard Marian Thomaiyar } 14290f2da3fSRichard Marian Thomaiyar try 14390f2da3fSRichard Marian Thomaiyar { 14490f2da3fSRichard Marian Thomaiyar updateSocketProperties(propertyMap); 14590f2da3fSRichard Marian Thomaiyar if (!iface) 14690f2da3fSRichard Marian Thomaiyar { 14790f2da3fSRichard Marian Thomaiyar registerProperties(); 14890f2da3fSRichard Marian Thomaiyar } 14990f2da3fSRichard Marian Thomaiyar } 15090f2da3fSRichard Marian Thomaiyar catch (const std::exception& e) 15190f2da3fSRichard Marian Thomaiyar { 15290f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 15390f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 15490f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 15590f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("WHAT=%s", 15690f2da3fSRichard Marian Thomaiyar e.what())); 15790f2da3fSRichard Marian Thomaiyar return; 15890f2da3fSRichard Marian Thomaiyar } 15990f2da3fSRichard Marian Thomaiyar }, 16090f2da3fSRichard Marian Thomaiyar sysdService, socketObjectPath, dBusPropIntf, 16190f2da3fSRichard Marian Thomaiyar dBusGetAllMethod, sysdSocketIntf); 16290f2da3fSRichard Marian Thomaiyar } 16390f2da3fSRichard Marian Thomaiyar else if (!iface) 16490f2da3fSRichard Marian Thomaiyar { 16590f2da3fSRichard Marian Thomaiyar registerProperties(); 16690f2da3fSRichard Marian Thomaiyar } 1670084047dSAppaRao Puli } 1680084047dSAppaRao Puli catch (const std::exception& e) 1690084047dSAppaRao Puli { 1700084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 17190f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 1720084047dSAppaRao Puli phosphor::logging::entry("WHAT=%s", e.what())); 1730084047dSAppaRao Puli return; 1740084047dSAppaRao Puli } 1750084047dSAppaRao Puli }, 17690f2da3fSRichard Marian Thomaiyar sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod, 17790f2da3fSRichard Marian Thomaiyar sysdUnitIntf); 1780084047dSAppaRao Puli return; 1790084047dSAppaRao Puli } 1800084047dSAppaRao Puli 18190f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf() 1820084047dSAppaRao Puli { 18390f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 1840084047dSAppaRao Puli { 18590f2da3fSRichard Marian Thomaiyar std::string socketUnitName(instantiatedUnitName + ".socket"); 1860084047dSAppaRao Puli /// Check override socket directory exist, if not create it. 1870084047dSAppaRao Puli std::experimental::filesystem::path ovrUnitFileDir( 1880084047dSAppaRao Puli systemdOverrideUnitBasePath); 1890084047dSAppaRao Puli ovrUnitFileDir += socketUnitName; 1900084047dSAppaRao Puli ovrUnitFileDir += ".d"; 1910084047dSAppaRao Puli if (!std::experimental::filesystem::exists(ovrUnitFileDir)) 1920084047dSAppaRao Puli { 19390f2da3fSRichard Marian Thomaiyar if (!std::experimental::filesystem::create_directories( 19490f2da3fSRichard Marian Thomaiyar ovrUnitFileDir)) 1950084047dSAppaRao Puli { 1960084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1970084047dSAppaRao Puli "Unable to create the directory.", 1980084047dSAppaRao Puli phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str())); 19990f2da3fSRichard Marian Thomaiyar phosphor::logging::elog<sdbusplus::xyz::openbmc_project:: 20090f2da3fSRichard Marian Thomaiyar Common::Error::InternalFailure>(); 20190f2da3fSRichard Marian Thomaiyar } 20290f2da3fSRichard Marian Thomaiyar } 20390f2da3fSRichard Marian Thomaiyar overrideConfDir = std::string(ovrUnitFileDir); 2040084047dSAppaRao Puli } 2050084047dSAppaRao Puli } 2060084047dSAppaRao Puli 20790f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig( 20890f2da3fSRichard Marian Thomaiyar sdbusplus::asio::object_server& srv_, 20990f2da3fSRichard Marian Thomaiyar std::shared_ptr<sdbusplus::asio::connection>& conn_, 21090f2da3fSRichard Marian Thomaiyar const std::string& objPath_, const std::string& baseUnitName_, 21190f2da3fSRichard Marian Thomaiyar const std::string& instanceName_, const std::string& serviceObjPath_, 21290f2da3fSRichard Marian Thomaiyar const std::string& socketObjPath_) : 21390f2da3fSRichard Marian Thomaiyar server(srv_), 21490f2da3fSRichard Marian Thomaiyar conn(conn_), objPath(objPath_), baseUnitName(baseUnitName_), 21590f2da3fSRichard Marian Thomaiyar instanceName(instanceName_), serviceObjectPath(serviceObjPath_), 21690f2da3fSRichard Marian Thomaiyar socketObjectPath(socketObjPath_) 21790f2da3fSRichard Marian Thomaiyar { 21890f2da3fSRichard Marian Thomaiyar instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@"); 2190084047dSAppaRao Puli updatedFlag = 0; 22090f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 2210084047dSAppaRao Puli return; 2220084047dSAppaRao Puli } 2230084047dSAppaRao Puli 22490f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName() 2250084047dSAppaRao Puli { 22690f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".socket"; 227e55cfd6eSAppaRao Puli } 228e55cfd6eSAppaRao Puli 22990f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName() 23090f2da3fSRichard Marian Thomaiyar { 23190f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".service"; 23290f2da3fSRichard Marian Thomaiyar } 23390f2da3fSRichard Marian Thomaiyar 23490f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut() 23590f2da3fSRichard Marian Thomaiyar { 23690f2da3fSRichard Marian Thomaiyar // return true if state is masked & no request to update the maskedState 23790f2da3fSRichard Marian Thomaiyar return ( 23890f2da3fSRichard Marian Thomaiyar stateValue == "masked" && 23990f2da3fSRichard Marian Thomaiyar !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState)))); 24090f2da3fSRichard Marian Thomaiyar } 24190f2da3fSRichard Marian Thomaiyar 24290f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield) 24390f2da3fSRichard Marian Thomaiyar { 24490f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 24590f2da3fSRichard Marian Thomaiyar { 24690f2da3fSRichard Marian Thomaiyar // No updates / masked - Just return. 24790f2da3fSRichard Marian Thomaiyar return; 24890f2da3fSRichard Marian Thomaiyar } 2490084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::INFO>( 2500084047dSAppaRao Puli "Applying new settings.", 2510084047dSAppaRao Puli phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 25290f2da3fSRichard Marian Thomaiyar if (subStateValue == "running") 2530084047dSAppaRao Puli { 25490f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 25590f2da3fSRichard Marian Thomaiyar { 25690f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit); 25790f2da3fSRichard Marian Thomaiyar } 25890f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit); 25990f2da3fSRichard Marian Thomaiyar } 26090f2da3fSRichard Marian Thomaiyar 26190f2da3fSRichard Marian Thomaiyar if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port))) 26290f2da3fSRichard Marian Thomaiyar { 26390f2da3fSRichard Marian Thomaiyar createSocketOverrideConf(); 2640084047dSAppaRao Puli // Create override config file and write data. 26590f2da3fSRichard Marian Thomaiyar std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName}; 2660084047dSAppaRao Puli std::string tmpFile{ovrCfgFile + "_tmp"}; 2670084047dSAppaRao Puli std::ofstream cfgFile(tmpFile, std::ios::out); 2680084047dSAppaRao Puli if (!cfgFile.good()) 2690084047dSAppaRao Puli { 2700084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2710084047dSAppaRao Puli "Failed to open override.conf_tmp file"); 2720084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2730084047dSAppaRao Puli Error::InternalFailure>(); 2740084047dSAppaRao Puli } 2750084047dSAppaRao Puli 2760084047dSAppaRao Puli // Write the socket header 2770084047dSAppaRao Puli cfgFile << "[Socket]\n"; 2780084047dSAppaRao Puli // Listen 2790084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" 2800084047dSAppaRao Puli << "\n"; 2810084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" << portNum << "\n"; 2820084047dSAppaRao Puli cfgFile.close(); 2830084047dSAppaRao Puli 2840084047dSAppaRao Puli if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0) 2850084047dSAppaRao Puli { 2860084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2870084047dSAppaRao Puli "Failed to rename tmp file as override.conf"); 2880084047dSAppaRao Puli std::remove(tmpFile.c_str()); 2890084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2900084047dSAppaRao Puli Error::InternalFailure>(); 2910084047dSAppaRao Puli } 292e55cfd6eSAppaRao Puli } 2930084047dSAppaRao Puli 29490f2da3fSRichard Marian Thomaiyar if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 29590f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)))) 296e55cfd6eSAppaRao Puli { 29790f2da3fSRichard Marian Thomaiyar std::vector<std::string> unitFiles; 29890f2da3fSRichard Marian Thomaiyar if (socketObjectPath.empty()) 29990f2da3fSRichard Marian Thomaiyar { 30090f2da3fSRichard Marian Thomaiyar unitFiles = {getServiceUnitName()}; 301e55cfd6eSAppaRao Puli } 30290f2da3fSRichard Marian Thomaiyar else 303e55cfd6eSAppaRao Puli { 30490f2da3fSRichard Marian Thomaiyar unitFiles = {getSocketUnitName(), getServiceUnitName()}; 30590f2da3fSRichard Marian Thomaiyar } 30690f2da3fSRichard Marian Thomaiyar systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue, 30790f2da3fSRichard Marian Thomaiyar unitMaskedState, unitEnabledState); 30890f2da3fSRichard Marian Thomaiyar } 30990f2da3fSRichard Marian Thomaiyar return; 31090f2da3fSRichard Marian Thomaiyar } 31190f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield) 31290f2da3fSRichard Marian Thomaiyar { 31390f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 31490f2da3fSRichard Marian Thomaiyar { 31590f2da3fSRichard Marian Thomaiyar // No updates. Just return. 31690f2da3fSRichard Marian Thomaiyar return; 3170084047dSAppaRao Puli } 3180084047dSAppaRao Puli 31990f2da3fSRichard Marian Thomaiyar if (unitRunningState) 3200084047dSAppaRao Puli { 32190f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 32290f2da3fSRichard Marian Thomaiyar { 32390f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), 32490f2da3fSRichard Marian Thomaiyar sysdRestartUnit); 3250084047dSAppaRao Puli } 32690f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit); 3270084047dSAppaRao Puli } 3280084047dSAppaRao Puli 3290084047dSAppaRao Puli // Reset the flag 3300084047dSAppaRao Puli updatedFlag = 0; 3310084047dSAppaRao Puli 33290f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::INFO>( 33390f2da3fSRichard Marian Thomaiyar "Applied new settings", 33490f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 3350084047dSAppaRao Puli 33690f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 3370084047dSAppaRao Puli return; 3380084047dSAppaRao Puli } 3390084047dSAppaRao Puli 3400084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer() 3410084047dSAppaRao Puli { 34233816cf9SRichard Marian Thomaiyar timer->expires_after(std::chrono::seconds(restartTimeout)); 3430084047dSAppaRao Puli timer->async_wait([this](const boost::system::error_code& ec) { 3440084047dSAppaRao Puli if (ec == boost::asio::error::operation_aborted) 3450084047dSAppaRao Puli { 3460084047dSAppaRao Puli // Timer reset. 3470084047dSAppaRao Puli return; 3480084047dSAppaRao Puli } 3490084047dSAppaRao Puli else if (ec) 3500084047dSAppaRao Puli { 3510084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 3520084047dSAppaRao Puli "async wait error."); 3530084047dSAppaRao Puli return; 3540084047dSAppaRao Puli } 35590f2da3fSRichard Marian Thomaiyar updateInProgress = true; 35690f2da3fSRichard Marian Thomaiyar boost::asio::spawn(conn->get_io_context(), 35790f2da3fSRichard Marian Thomaiyar [this](boost::asio::yield_context yield) { 35890f2da3fSRichard Marian Thomaiyar // Stop and apply configuration for all objects 3590084047dSAppaRao Puli for (auto& srvMgrObj : srvMgrObjects) 3600084047dSAppaRao Puli { 3610084047dSAppaRao Puli auto& srvObj = srvMgrObj.second; 3620084047dSAppaRao Puli if (srvObj->updatedFlag) 3630084047dSAppaRao Puli { 36490f2da3fSRichard Marian Thomaiyar srvObj->stopAndApplyUnitConfig(yield); 3650084047dSAppaRao Puli } 3660084047dSAppaRao Puli } 36790f2da3fSRichard Marian Thomaiyar // Do system reload 36890f2da3fSRichard Marian Thomaiyar systemdDaemonReload(conn, yield); 36990f2da3fSRichard Marian Thomaiyar // restart unit config. 37090f2da3fSRichard Marian Thomaiyar for (auto& srvMgrObj : srvMgrObjects) 37190f2da3fSRichard Marian Thomaiyar { 37290f2da3fSRichard Marian Thomaiyar auto& srvObj = srvMgrObj.second; 37390f2da3fSRichard Marian Thomaiyar if (srvObj->updatedFlag) 37490f2da3fSRichard Marian Thomaiyar { 37590f2da3fSRichard Marian Thomaiyar srvObj->restartUnitConfig(yield); 37690f2da3fSRichard Marian Thomaiyar } 37790f2da3fSRichard Marian Thomaiyar } 37890f2da3fSRichard Marian Thomaiyar updateInProgress = false; 37990f2da3fSRichard Marian Thomaiyar }); 3800084047dSAppaRao Puli }); 3810084047dSAppaRao Puli } 3820084047dSAppaRao Puli 3830084047dSAppaRao Puli void ServiceConfig::registerProperties() 3840084047dSAppaRao Puli { 38590f2da3fSRichard Marian Thomaiyar iface = server.add_interface(objPath, serviceConfigIntfName); 3860084047dSAppaRao Puli 38790f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 38890f2da3fSRichard Marian Thomaiyar { 3890084047dSAppaRao Puli iface->register_property( 39090f2da3fSRichard Marian Thomaiyar srvCfgPropPort, portNum, 39190f2da3fSRichard Marian Thomaiyar [this](const uint16_t& req, uint16_t& res) { 39290f2da3fSRichard Marian Thomaiyar if (!internalSet) 39390f2da3fSRichard Marian Thomaiyar { 3940084047dSAppaRao Puli if (req == res) 3950084047dSAppaRao Puli { 3960084047dSAppaRao Puli return 1; 3970084047dSAppaRao Puli } 39890f2da3fSRichard Marian Thomaiyar if (updateInProgress) 39990f2da3fSRichard Marian Thomaiyar { 40090f2da3fSRichard Marian Thomaiyar return 0; 40190f2da3fSRichard Marian Thomaiyar } 4020084047dSAppaRao Puli portNum = req; 40390f2da3fSRichard Marian Thomaiyar updatedFlag |= 40490f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::port)); 4050084047dSAppaRao Puli startServiceRestartTimer(); 40690f2da3fSRichard Marian Thomaiyar } 40790f2da3fSRichard Marian Thomaiyar res = req; 40890f2da3fSRichard Marian Thomaiyar return 1; 40990f2da3fSRichard Marian Thomaiyar }); 41090f2da3fSRichard Marian Thomaiyar } 41190f2da3fSRichard Marian Thomaiyar 41290f2da3fSRichard Marian Thomaiyar iface->register_property( 41390f2da3fSRichard Marian Thomaiyar srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) { 41490f2da3fSRichard Marian Thomaiyar if (!internalSet) 41590f2da3fSRichard Marian Thomaiyar { 41690f2da3fSRichard Marian Thomaiyar if (req == res) 41790f2da3fSRichard Marian Thomaiyar { 41890f2da3fSRichard Marian Thomaiyar return 1; 41990f2da3fSRichard Marian Thomaiyar } 42090f2da3fSRichard Marian Thomaiyar if (updateInProgress) 42190f2da3fSRichard Marian Thomaiyar { 42290f2da3fSRichard Marian Thomaiyar return 0; 42390f2da3fSRichard Marian Thomaiyar } 42490f2da3fSRichard Marian Thomaiyar unitMaskedState = req; 42590f2da3fSRichard Marian Thomaiyar unitEnabledState = !unitMaskedState; 42690f2da3fSRichard Marian Thomaiyar unitRunningState = !unitMaskedState; 42790f2da3fSRichard Marian Thomaiyar updatedFlag |= 42890f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 42990f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) | 43090f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 43190f2da3fSRichard Marian Thomaiyar internalSet = true; 43290f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropEnabled, unitEnabledState); 43390f2da3fSRichard Marian Thomaiyar iface->set_property(srvCfgPropRunning, unitRunningState); 43490f2da3fSRichard Marian Thomaiyar internalSet = false; 43590f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 43690f2da3fSRichard Marian Thomaiyar } 4370084047dSAppaRao Puli res = req; 4380084047dSAppaRao Puli return 1; 4390084047dSAppaRao Puli }); 4400084047dSAppaRao Puli 4410084047dSAppaRao Puli iface->register_property( 44290f2da3fSRichard Marian Thomaiyar srvCfgPropEnabled, unitEnabledState, 44390f2da3fSRichard Marian Thomaiyar [this](const bool& req, bool& res) { 44490f2da3fSRichard Marian Thomaiyar if (!internalSet) 44590f2da3fSRichard Marian Thomaiyar { 4460084047dSAppaRao Puli if (req == res) 4470084047dSAppaRao Puli { 4480084047dSAppaRao Puli return 1; 4490084047dSAppaRao Puli } 45090f2da3fSRichard Marian Thomaiyar if (updateInProgress) 4510084047dSAppaRao Puli { 45290f2da3fSRichard Marian Thomaiyar return 0; 4530084047dSAppaRao Puli } 45490f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 45590f2da3fSRichard Marian Thomaiyar { // block updating if masked 4560084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 4570084047dSAppaRao Puli "Invalid value specified"); 4580084047dSAppaRao Puli return -EINVAL; 4590084047dSAppaRao Puli } 46090f2da3fSRichard Marian Thomaiyar unitEnabledState = req; 46190f2da3fSRichard Marian Thomaiyar updatedFlag |= 46290f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)); 4630084047dSAppaRao Puli startServiceRestartTimer(); 46490f2da3fSRichard Marian Thomaiyar } 46590f2da3fSRichard Marian Thomaiyar res = req; 46690f2da3fSRichard Marian Thomaiyar return 1; 46790f2da3fSRichard Marian Thomaiyar }); 46890f2da3fSRichard Marian Thomaiyar 46990f2da3fSRichard Marian Thomaiyar iface->register_property( 47090f2da3fSRichard Marian Thomaiyar srvCfgPropRunning, unitRunningState, 47190f2da3fSRichard Marian Thomaiyar [this](const bool& req, bool& res) { 47290f2da3fSRichard Marian Thomaiyar if (!internalSet) 47390f2da3fSRichard Marian Thomaiyar { 47490f2da3fSRichard Marian Thomaiyar if (req == res) 47590f2da3fSRichard Marian Thomaiyar { 47690f2da3fSRichard Marian Thomaiyar return 1; 47790f2da3fSRichard Marian Thomaiyar } 47890f2da3fSRichard Marian Thomaiyar if (updateInProgress) 47990f2da3fSRichard Marian Thomaiyar { 48090f2da3fSRichard Marian Thomaiyar return 0; 48190f2da3fSRichard Marian Thomaiyar } 48290f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 48390f2da3fSRichard Marian Thomaiyar { // block updating if masked 48490f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 48590f2da3fSRichard Marian Thomaiyar "Invalid value specified"); 48690f2da3fSRichard Marian Thomaiyar return -EINVAL; 48790f2da3fSRichard Marian Thomaiyar } 48890f2da3fSRichard Marian Thomaiyar unitRunningState = req; 48990f2da3fSRichard Marian Thomaiyar updatedFlag |= 49090f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 49190f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 49290f2da3fSRichard Marian Thomaiyar } 4930084047dSAppaRao Puli res = req; 4940084047dSAppaRao Puli return 1; 4950084047dSAppaRao Puli }); 4960084047dSAppaRao Puli 4970084047dSAppaRao Puli iface->initialize(); 4980084047dSAppaRao Puli return; 4990084047dSAppaRao Puli } 5000084047dSAppaRao Puli 5010084047dSAppaRao Puli } // namespace service 5020084047dSAppaRao Puli } // namespace phosphor 503