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 */ 16ee853eb2SAppaRao Puli #include "srvcfg_manager.hpp" 17ee853eb2SAppaRao Puli 18ee853eb2SAppaRao Puli #include <boost/asio/spawn.hpp> 19ee853eb2SAppaRao 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; 6183241c09STom Joseph if (sockAttrIface && sockAttrIface->is_initialized()) 6290f2da3fSRichard Marian Thomaiyar { 6390f2da3fSRichard Marian Thomaiyar internalSet = true; 6483241c09STom Joseph sockAttrIface->set_property(sockAttrPropPort, 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 } 8783241c09STom Joseph if (srvCfgIface && srvCfgIface->is_initialized()) 8890f2da3fSRichard Marian Thomaiyar { 8990f2da3fSRichard Marian Thomaiyar internalSet = true; 9083241c09STom Joseph srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState); 9183241c09STom Joseph srvCfgIface->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); 99*a19b5093SGeorge Liu if (subStateValue == subStateRunning || 100*a19b5093SGeorge Liu subStateValue == subStateListening) 10190f2da3fSRichard Marian Thomaiyar { 10290f2da3fSRichard Marian Thomaiyar unitRunningState = true; 10390f2da3fSRichard Marian Thomaiyar } 10483241c09STom Joseph if (srvCfgIface && srvCfgIface->is_initialized()) 10590f2da3fSRichard Marian Thomaiyar { 10690f2da3fSRichard Marian Thomaiyar internalSet = true; 10783241c09STom Joseph srvCfgIface->set_property(srvCfgPropRunning, unitRunningState); 10890f2da3fSRichard Marian Thomaiyar internalSet = false; 10990f2da3fSRichard Marian Thomaiyar } 11090f2da3fSRichard Marian Thomaiyar } 11190f2da3fSRichard Marian Thomaiyar } 11290f2da3fSRichard Marian Thomaiyar 11390f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties() 11490f2da3fSRichard Marian Thomaiyar { 115*a19b5093SGeorge Liu std::string objectPath = 116*a19b5093SGeorge Liu isDropBearService ? socketObjectPath : serviceObjectPath; 117*a19b5093SGeorge Liu if (objectPath.empty()) 118*a19b5093SGeorge Liu { 119*a19b5093SGeorge Liu return; 120*a19b5093SGeorge Liu } 121*a19b5093SGeorge Liu 12290f2da3fSRichard Marian Thomaiyar conn->async_method_call( 12390f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 124ee853eb2SAppaRao Puli const boost::container::flat_map<std::string, VariantType>& 125ee853eb2SAppaRao Puli propertyMap) { 12690f2da3fSRichard Marian Thomaiyar if (ec) 12790f2da3fSRichard Marian Thomaiyar { 12890f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 12990f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to service unit " 13090f2da3fSRichard Marian Thomaiyar "properties"); 13190f2da3fSRichard Marian Thomaiyar return; 13290f2da3fSRichard Marian Thomaiyar } 13390f2da3fSRichard Marian Thomaiyar try 13490f2da3fSRichard Marian Thomaiyar { 13590f2da3fSRichard Marian Thomaiyar updateServiceProperties(propertyMap); 13690f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 13790f2da3fSRichard Marian Thomaiyar { 13890f2da3fSRichard Marian Thomaiyar conn->async_method_call( 13990f2da3fSRichard Marian Thomaiyar [this](boost::system::error_code ec, 14090f2da3fSRichard Marian Thomaiyar const boost::container::flat_map< 14190f2da3fSRichard Marian Thomaiyar std::string, VariantType>& propertyMap) { 14290f2da3fSRichard Marian Thomaiyar if (ec) 14390f2da3fSRichard Marian Thomaiyar { 14490f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 14590f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 14690f2da3fSRichard Marian Thomaiyar "async_method_call error: Failed to get " 14790f2da3fSRichard Marian Thomaiyar "all property"); 14890f2da3fSRichard Marian Thomaiyar return; 14990f2da3fSRichard Marian Thomaiyar } 15090f2da3fSRichard Marian Thomaiyar try 15190f2da3fSRichard Marian Thomaiyar { 15290f2da3fSRichard Marian Thomaiyar updateSocketProperties(propertyMap); 15383241c09STom Joseph if (!srvCfgIface) 15490f2da3fSRichard Marian Thomaiyar { 15590f2da3fSRichard Marian Thomaiyar registerProperties(); 15690f2da3fSRichard Marian Thomaiyar } 15790f2da3fSRichard Marian Thomaiyar } 15890f2da3fSRichard Marian Thomaiyar catch (const std::exception& e) 15990f2da3fSRichard Marian Thomaiyar { 16090f2da3fSRichard Marian Thomaiyar phosphor::logging::log< 16190f2da3fSRichard Marian Thomaiyar phosphor::logging::level::ERR>( 16290f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 16390f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("WHAT=%s", 16490f2da3fSRichard Marian Thomaiyar e.what())); 16590f2da3fSRichard Marian Thomaiyar return; 16690f2da3fSRichard Marian Thomaiyar } 16790f2da3fSRichard Marian Thomaiyar }, 16890f2da3fSRichard Marian Thomaiyar sysdService, socketObjectPath, dBusPropIntf, 16990f2da3fSRichard Marian Thomaiyar dBusGetAllMethod, sysdSocketIntf); 17090f2da3fSRichard Marian Thomaiyar } 17183241c09STom Joseph else if (!srvCfgIface) 17290f2da3fSRichard Marian Thomaiyar { 17390f2da3fSRichard Marian Thomaiyar registerProperties(); 17490f2da3fSRichard Marian Thomaiyar } 1750084047dSAppaRao Puli } 1760084047dSAppaRao Puli catch (const std::exception& e) 1770084047dSAppaRao Puli { 1780084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 17990f2da3fSRichard Marian Thomaiyar "Exception in getting socket properties", 1800084047dSAppaRao Puli phosphor::logging::entry("WHAT=%s", e.what())); 1810084047dSAppaRao Puli return; 1820084047dSAppaRao Puli } 1830084047dSAppaRao Puli }, 184*a19b5093SGeorge Liu sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf); 1850084047dSAppaRao Puli return; 1860084047dSAppaRao Puli } 1870084047dSAppaRao Puli 18890f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf() 1890084047dSAppaRao Puli { 19090f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 1910084047dSAppaRao Puli { 19290f2da3fSRichard Marian Thomaiyar std::string socketUnitName(instantiatedUnitName + ".socket"); 1930084047dSAppaRao Puli /// Check override socket directory exist, if not create it. 19482e9557eSTom Joseph std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath); 1950084047dSAppaRao Puli ovrUnitFileDir += socketUnitName; 1960084047dSAppaRao Puli ovrUnitFileDir += ".d"; 19782e9557eSTom Joseph if (!std::filesystem::exists(ovrUnitFileDir)) 1980084047dSAppaRao Puli { 19982e9557eSTom Joseph if (!std::filesystem::create_directories(ovrUnitFileDir)) 2000084047dSAppaRao Puli { 2010084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2020084047dSAppaRao Puli "Unable to create the directory.", 2030084047dSAppaRao Puli phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str())); 20490f2da3fSRichard Marian Thomaiyar phosphor::logging::elog<sdbusplus::xyz::openbmc_project:: 20590f2da3fSRichard Marian Thomaiyar Common::Error::InternalFailure>(); 20690f2da3fSRichard Marian Thomaiyar } 20790f2da3fSRichard Marian Thomaiyar } 20890f2da3fSRichard Marian Thomaiyar overrideConfDir = std::string(ovrUnitFileDir); 2090084047dSAppaRao Puli } 2100084047dSAppaRao Puli } 2110084047dSAppaRao Puli 21290f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig( 21390f2da3fSRichard Marian Thomaiyar sdbusplus::asio::object_server& srv_, 21490f2da3fSRichard Marian Thomaiyar std::shared_ptr<sdbusplus::asio::connection>& conn_, 21590f2da3fSRichard Marian Thomaiyar const std::string& objPath_, const std::string& baseUnitName_, 21690f2da3fSRichard Marian Thomaiyar const std::string& instanceName_, const std::string& serviceObjPath_, 21790f2da3fSRichard Marian Thomaiyar const std::string& socketObjPath_) : 21882e9557eSTom Joseph conn(conn_), 21982e9557eSTom Joseph server(srv_), objPath(objPath_), baseUnitName(baseUnitName_), 22090f2da3fSRichard Marian Thomaiyar instanceName(instanceName_), serviceObjectPath(serviceObjPath_), 22190f2da3fSRichard Marian Thomaiyar socketObjectPath(socketObjPath_) 22290f2da3fSRichard Marian Thomaiyar { 223*a19b5093SGeorge Liu if (baseUnitName == "dropbear") 224*a19b5093SGeorge Liu { 225*a19b5093SGeorge Liu isDropBearService = true; 226*a19b5093SGeorge Liu } 22790f2da3fSRichard Marian Thomaiyar instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@"); 2280084047dSAppaRao Puli updatedFlag = 0; 22990f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 2300084047dSAppaRao Puli return; 2310084047dSAppaRao Puli } 2320084047dSAppaRao Puli 23390f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName() 2340084047dSAppaRao Puli { 23590f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".socket"; 236e55cfd6eSAppaRao Puli } 237e55cfd6eSAppaRao Puli 23890f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName() 23990f2da3fSRichard Marian Thomaiyar { 24090f2da3fSRichard Marian Thomaiyar return instantiatedUnitName + ".service"; 24190f2da3fSRichard Marian Thomaiyar } 24290f2da3fSRichard Marian Thomaiyar 24390f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut() 24490f2da3fSRichard Marian Thomaiyar { 24590f2da3fSRichard Marian Thomaiyar // return true if state is masked & no request to update the maskedState 24690f2da3fSRichard Marian Thomaiyar return ( 24790f2da3fSRichard Marian Thomaiyar stateValue == "masked" && 24890f2da3fSRichard Marian Thomaiyar !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState)))); 24990f2da3fSRichard Marian Thomaiyar } 25090f2da3fSRichard Marian Thomaiyar 25190f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield) 25290f2da3fSRichard Marian Thomaiyar { 25390f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 25490f2da3fSRichard Marian Thomaiyar { 25590f2da3fSRichard Marian Thomaiyar // No updates / masked - Just return. 25690f2da3fSRichard Marian Thomaiyar return; 25790f2da3fSRichard Marian Thomaiyar } 2580084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::INFO>( 2590084047dSAppaRao Puli "Applying new settings.", 2600084047dSAppaRao Puli phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 261*a19b5093SGeorge Liu if (subStateValue == subStateRunning || subStateValue == subStateListening) 2620084047dSAppaRao Puli { 26390f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 26490f2da3fSRichard Marian Thomaiyar { 26590f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit); 26690f2da3fSRichard Marian Thomaiyar } 267*a19b5093SGeorge Liu if (!isDropBearService) 268*a19b5093SGeorge Liu { 26990f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit); 27090f2da3fSRichard Marian Thomaiyar } 271*a19b5093SGeorge Liu else 272*a19b5093SGeorge Liu { 273*a19b5093SGeorge Liu // Get the ListUnits property, find all the services of 274*a19b5093SGeorge Liu // `dropbear@<ip><port>.service` and stop the service through 275*a19b5093SGeorge Liu // the systemdUnitAction method 276*a19b5093SGeorge Liu boost::system::error_code ec; 277*a19b5093SGeorge Liu auto listUnits = 278*a19b5093SGeorge Liu conn->yield_method_call<std::vector<ListUnitsType>>( 279*a19b5093SGeorge Liu yield, ec, sysdService, sysdObjPath, sysdMgrIntf, 280*a19b5093SGeorge Liu "ListUnits"); 281*a19b5093SGeorge Liu 282*a19b5093SGeorge Liu checkAndThrowInternalFailure( 283*a19b5093SGeorge Liu ec, "yield_method_call error: ListUnits failed"); 284*a19b5093SGeorge Liu 285*a19b5093SGeorge Liu for (const auto& unit : listUnits) 286*a19b5093SGeorge Liu { 287*a19b5093SGeorge Liu const auto& service = 288*a19b5093SGeorge Liu std::get<static_cast<int>(ListUnitElements::name)>(unit); 289*a19b5093SGeorge Liu const auto& status = 290*a19b5093SGeorge Liu std::get<static_cast<int>(ListUnitElements::subState)>( 291*a19b5093SGeorge Liu unit); 292*a19b5093SGeorge Liu if (service.find("dropbear@") != std::string::npos && 293*a19b5093SGeorge Liu service.find(".service") != std::string::npos && 294*a19b5093SGeorge Liu status == subStateRunning) 295*a19b5093SGeorge Liu { 296*a19b5093SGeorge Liu systemdUnitAction(conn, yield, service, sysdStopUnit); 297*a19b5093SGeorge Liu } 298*a19b5093SGeorge Liu } 299*a19b5093SGeorge Liu } 300*a19b5093SGeorge Liu } 30190f2da3fSRichard Marian Thomaiyar 30290f2da3fSRichard Marian Thomaiyar if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port))) 30390f2da3fSRichard Marian Thomaiyar { 30490f2da3fSRichard Marian Thomaiyar createSocketOverrideConf(); 3050084047dSAppaRao Puli // Create override config file and write data. 30690f2da3fSRichard Marian Thomaiyar std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName}; 3070084047dSAppaRao Puli std::string tmpFile{ovrCfgFile + "_tmp"}; 3080084047dSAppaRao Puli std::ofstream cfgFile(tmpFile, std::ios::out); 3090084047dSAppaRao Puli if (!cfgFile.good()) 3100084047dSAppaRao Puli { 3110084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 3120084047dSAppaRao Puli "Failed to open override.conf_tmp file"); 3130084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 3140084047dSAppaRao Puli Error::InternalFailure>(); 3150084047dSAppaRao Puli } 3160084047dSAppaRao Puli 3170084047dSAppaRao Puli // Write the socket header 3180084047dSAppaRao Puli cfgFile << "[Socket]\n"; 3190084047dSAppaRao Puli // Listen 3200084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" 3210084047dSAppaRao Puli << "\n"; 3220084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" << portNum << "\n"; 3230084047dSAppaRao Puli cfgFile.close(); 3240084047dSAppaRao Puli 3250084047dSAppaRao Puli if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0) 3260084047dSAppaRao Puli { 3270084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 3280084047dSAppaRao Puli "Failed to rename tmp file as override.conf"); 3290084047dSAppaRao Puli std::remove(tmpFile.c_str()); 3300084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 3310084047dSAppaRao Puli Error::InternalFailure>(); 3320084047dSAppaRao Puli } 333e55cfd6eSAppaRao Puli } 3340084047dSAppaRao Puli 33590f2da3fSRichard Marian Thomaiyar if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 33690f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)))) 337e55cfd6eSAppaRao Puli { 33890f2da3fSRichard Marian Thomaiyar std::vector<std::string> unitFiles; 33990f2da3fSRichard Marian Thomaiyar if (socketObjectPath.empty()) 34090f2da3fSRichard Marian Thomaiyar { 34190f2da3fSRichard Marian Thomaiyar unitFiles = {getServiceUnitName()}; 342e55cfd6eSAppaRao Puli } 343*a19b5093SGeorge Liu else if (!socketObjectPath.empty() && isDropBearService) 344*a19b5093SGeorge Liu { 345*a19b5093SGeorge Liu unitFiles = {getSocketUnitName()}; 346*a19b5093SGeorge Liu } 34790f2da3fSRichard Marian Thomaiyar else 348e55cfd6eSAppaRao Puli { 34990f2da3fSRichard Marian Thomaiyar unitFiles = {getSocketUnitName(), getServiceUnitName()}; 35090f2da3fSRichard Marian Thomaiyar } 35190f2da3fSRichard Marian Thomaiyar systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue, 35290f2da3fSRichard Marian Thomaiyar unitMaskedState, unitEnabledState); 35390f2da3fSRichard Marian Thomaiyar } 35490f2da3fSRichard Marian Thomaiyar return; 35590f2da3fSRichard Marian Thomaiyar } 35690f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield) 35790f2da3fSRichard Marian Thomaiyar { 35890f2da3fSRichard Marian Thomaiyar if (!updatedFlag || isMaskedOut()) 35990f2da3fSRichard Marian Thomaiyar { 36090f2da3fSRichard Marian Thomaiyar // No updates. Just return. 36190f2da3fSRichard Marian Thomaiyar return; 3620084047dSAppaRao Puli } 3630084047dSAppaRao Puli 36490f2da3fSRichard Marian Thomaiyar if (unitRunningState) 3650084047dSAppaRao Puli { 36690f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 36790f2da3fSRichard Marian Thomaiyar { 36890f2da3fSRichard Marian Thomaiyar systemdUnitAction(conn, yield, getSocketUnitName(), 36990f2da3fSRichard Marian Thomaiyar sysdRestartUnit); 3700084047dSAppaRao Puli } 371*a19b5093SGeorge Liu if (!isDropBearService) 372*a19b5093SGeorge Liu { 373*a19b5093SGeorge Liu systemdUnitAction(conn, yield, getServiceUnitName(), 374*a19b5093SGeorge Liu sysdRestartUnit); 375*a19b5093SGeorge Liu } 3760084047dSAppaRao Puli } 3770084047dSAppaRao Puli 3780084047dSAppaRao Puli // Reset the flag 3790084047dSAppaRao Puli updatedFlag = 0; 3800084047dSAppaRao Puli 38190f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::INFO>( 38290f2da3fSRichard Marian Thomaiyar "Applied new settings", 38390f2da3fSRichard Marian Thomaiyar phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 3840084047dSAppaRao Puli 38590f2da3fSRichard Marian Thomaiyar queryAndUpdateProperties(); 3860084047dSAppaRao Puli return; 3870084047dSAppaRao Puli } 3880084047dSAppaRao Puli 3890084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer() 3900084047dSAppaRao Puli { 39133816cf9SRichard Marian Thomaiyar timer->expires_after(std::chrono::seconds(restartTimeout)); 3920084047dSAppaRao Puli timer->async_wait([this](const boost::system::error_code& ec) { 3930084047dSAppaRao Puli if (ec == boost::asio::error::operation_aborted) 3940084047dSAppaRao Puli { 3950084047dSAppaRao Puli // Timer reset. 3960084047dSAppaRao Puli return; 3970084047dSAppaRao Puli } 3980084047dSAppaRao Puli else if (ec) 3990084047dSAppaRao Puli { 4000084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 4010084047dSAppaRao Puli "async wait error."); 4020084047dSAppaRao Puli return; 4030084047dSAppaRao Puli } 40490f2da3fSRichard Marian Thomaiyar updateInProgress = true; 40590f2da3fSRichard Marian Thomaiyar boost::asio::spawn(conn->get_io_context(), 40690f2da3fSRichard Marian Thomaiyar [this](boost::asio::yield_context yield) { 40790f2da3fSRichard Marian Thomaiyar // Stop and apply configuration for all objects 4080084047dSAppaRao Puli for (auto& srvMgrObj : srvMgrObjects) 4090084047dSAppaRao Puli { 4100084047dSAppaRao Puli auto& srvObj = srvMgrObj.second; 4110084047dSAppaRao Puli if (srvObj->updatedFlag) 4120084047dSAppaRao Puli { 41390f2da3fSRichard Marian Thomaiyar srvObj->stopAndApplyUnitConfig(yield); 4140084047dSAppaRao Puli } 4150084047dSAppaRao Puli } 41690f2da3fSRichard Marian Thomaiyar // Do system reload 41790f2da3fSRichard Marian Thomaiyar systemdDaemonReload(conn, yield); 41890f2da3fSRichard Marian Thomaiyar // restart unit config. 41990f2da3fSRichard Marian Thomaiyar for (auto& srvMgrObj : srvMgrObjects) 42090f2da3fSRichard Marian Thomaiyar { 42190f2da3fSRichard Marian Thomaiyar auto& srvObj = srvMgrObj.second; 42290f2da3fSRichard Marian Thomaiyar if (srvObj->updatedFlag) 42390f2da3fSRichard Marian Thomaiyar { 42490f2da3fSRichard Marian Thomaiyar srvObj->restartUnitConfig(yield); 42590f2da3fSRichard Marian Thomaiyar } 42690f2da3fSRichard Marian Thomaiyar } 42790f2da3fSRichard Marian Thomaiyar updateInProgress = false; 42890f2da3fSRichard Marian Thomaiyar }); 4290084047dSAppaRao Puli }); 4300084047dSAppaRao Puli } 4310084047dSAppaRao Puli 4320084047dSAppaRao Puli void ServiceConfig::registerProperties() 4330084047dSAppaRao Puli { 43483241c09STom Joseph srvCfgIface = server.add_interface(objPath, serviceConfigIntfName); 4350084047dSAppaRao Puli 43690f2da3fSRichard Marian Thomaiyar if (!socketObjectPath.empty()) 43790f2da3fSRichard Marian Thomaiyar { 43883241c09STom Joseph sockAttrIface = server.add_interface(objPath, sockAttrIntfName); 43983241c09STom Joseph sockAttrIface->register_property( 44083241c09STom Joseph sockAttrPropPort, portNum, 44190f2da3fSRichard Marian Thomaiyar [this](const uint16_t& req, uint16_t& 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) 44990f2da3fSRichard Marian Thomaiyar { 45090f2da3fSRichard Marian Thomaiyar return 0; 45190f2da3fSRichard Marian Thomaiyar } 4520084047dSAppaRao Puli portNum = req; 45390f2da3fSRichard Marian Thomaiyar updatedFlag |= 45490f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::port)); 4550084047dSAppaRao Puli startServiceRestartTimer(); 45690f2da3fSRichard Marian Thomaiyar } 45790f2da3fSRichard Marian Thomaiyar res = req; 45890f2da3fSRichard Marian Thomaiyar return 1; 45990f2da3fSRichard Marian Thomaiyar }); 46090f2da3fSRichard Marian Thomaiyar } 46190f2da3fSRichard Marian Thomaiyar 46283241c09STom Joseph srvCfgIface->register_property( 46390f2da3fSRichard Marian Thomaiyar srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) { 46490f2da3fSRichard Marian Thomaiyar if (!internalSet) 46590f2da3fSRichard Marian Thomaiyar { 46690f2da3fSRichard Marian Thomaiyar if (req == res) 46790f2da3fSRichard Marian Thomaiyar { 46890f2da3fSRichard Marian Thomaiyar return 1; 46990f2da3fSRichard Marian Thomaiyar } 47090f2da3fSRichard Marian Thomaiyar if (updateInProgress) 47190f2da3fSRichard Marian Thomaiyar { 47290f2da3fSRichard Marian Thomaiyar return 0; 47390f2da3fSRichard Marian Thomaiyar } 47490f2da3fSRichard Marian Thomaiyar unitMaskedState = req; 47590f2da3fSRichard Marian Thomaiyar unitEnabledState = !unitMaskedState; 47690f2da3fSRichard Marian Thomaiyar unitRunningState = !unitMaskedState; 47790f2da3fSRichard Marian Thomaiyar updatedFlag |= 47890f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) | 47990f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) | 48090f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 48190f2da3fSRichard Marian Thomaiyar internalSet = true; 48283241c09STom Joseph srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState); 48383241c09STom Joseph srvCfgIface->set_property(srvCfgPropRunning, unitRunningState); 48490f2da3fSRichard Marian Thomaiyar internalSet = false; 48590f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 48690f2da3fSRichard Marian Thomaiyar } 4870084047dSAppaRao Puli res = req; 4880084047dSAppaRao Puli return 1; 4890084047dSAppaRao Puli }); 4900084047dSAppaRao Puli 49183241c09STom Joseph srvCfgIface->register_property( 49290f2da3fSRichard Marian Thomaiyar srvCfgPropEnabled, unitEnabledState, 49390f2da3fSRichard Marian Thomaiyar [this](const bool& req, bool& res) { 49490f2da3fSRichard Marian Thomaiyar if (!internalSet) 49590f2da3fSRichard Marian Thomaiyar { 4960084047dSAppaRao Puli if (req == res) 4970084047dSAppaRao Puli { 4980084047dSAppaRao Puli return 1; 4990084047dSAppaRao Puli } 50090f2da3fSRichard Marian Thomaiyar if (updateInProgress) 5010084047dSAppaRao Puli { 50290f2da3fSRichard Marian Thomaiyar return 0; 5030084047dSAppaRao Puli } 50490f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 50590f2da3fSRichard Marian Thomaiyar { // block updating if masked 5060084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 5070084047dSAppaRao Puli "Invalid value specified"); 5080084047dSAppaRao Puli return -EINVAL; 5090084047dSAppaRao Puli } 51090f2da3fSRichard Marian Thomaiyar unitEnabledState = req; 51190f2da3fSRichard Marian Thomaiyar updatedFlag |= 51290f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::enabledState)); 5130084047dSAppaRao Puli startServiceRestartTimer(); 51490f2da3fSRichard Marian Thomaiyar } 51590f2da3fSRichard Marian Thomaiyar res = req; 51690f2da3fSRichard Marian Thomaiyar return 1; 51790f2da3fSRichard Marian Thomaiyar }); 51890f2da3fSRichard Marian Thomaiyar 51983241c09STom Joseph srvCfgIface->register_property( 52090f2da3fSRichard Marian Thomaiyar srvCfgPropRunning, unitRunningState, 52190f2da3fSRichard Marian Thomaiyar [this](const bool& req, bool& res) { 52290f2da3fSRichard Marian Thomaiyar if (!internalSet) 52390f2da3fSRichard Marian Thomaiyar { 52490f2da3fSRichard Marian Thomaiyar if (req == res) 52590f2da3fSRichard Marian Thomaiyar { 52690f2da3fSRichard Marian Thomaiyar return 1; 52790f2da3fSRichard Marian Thomaiyar } 52890f2da3fSRichard Marian Thomaiyar if (updateInProgress) 52990f2da3fSRichard Marian Thomaiyar { 53090f2da3fSRichard Marian Thomaiyar return 0; 53190f2da3fSRichard Marian Thomaiyar } 53290f2da3fSRichard Marian Thomaiyar if (unitMaskedState) 53390f2da3fSRichard Marian Thomaiyar { // block updating if masked 53490f2da3fSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 53590f2da3fSRichard Marian Thomaiyar "Invalid value specified"); 53690f2da3fSRichard Marian Thomaiyar return -EINVAL; 53790f2da3fSRichard Marian Thomaiyar } 53890f2da3fSRichard Marian Thomaiyar unitRunningState = req; 53990f2da3fSRichard Marian Thomaiyar updatedFlag |= 54090f2da3fSRichard Marian Thomaiyar (1 << static_cast<uint8_t>(UpdatedProp::runningState)); 54190f2da3fSRichard Marian Thomaiyar startServiceRestartTimer(); 54290f2da3fSRichard Marian Thomaiyar } 5430084047dSAppaRao Puli res = req; 5440084047dSAppaRao Puli return 1; 5450084047dSAppaRao Puli }); 5460084047dSAppaRao Puli 54783241c09STom Joseph srvCfgIface->initialize(); 54883241c09STom Joseph if (!socketObjectPath.empty()) 54983241c09STom Joseph { 55083241c09STom Joseph sockAttrIface->initialize(); 55183241c09STom Joseph } 5520084047dSAppaRao Puli return; 5530084047dSAppaRao Puli } 5540084047dSAppaRao Puli 5550084047dSAppaRao Puli } // namespace service 5560084047dSAppaRao Puli } // namespace phosphor 557