1*0084047dSAppaRao Puli /* 2*0084047dSAppaRao Puli // Copyright (c) 2018 Intel Corporation 3*0084047dSAppaRao Puli // 4*0084047dSAppaRao Puli // Licensed under the Apache License, Version 2.0 (the "License"); 5*0084047dSAppaRao Puli // you may not use this file except in compliance with the License. 6*0084047dSAppaRao Puli // You may obtain a copy of the License at 7*0084047dSAppaRao Puli // 8*0084047dSAppaRao Puli // http://www.apache.org/licenses/LICENSE-2.0 9*0084047dSAppaRao Puli // 10*0084047dSAppaRao Puli // Unless required by applicable law or agreed to in writing, software 11*0084047dSAppaRao Puli // distributed under the License is distributed on an "AS IS" BASIS, 12*0084047dSAppaRao Puli // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*0084047dSAppaRao Puli // See the License for the specific language governing permissions and 14*0084047dSAppaRao Puli // limitations under the License. 15*0084047dSAppaRao Puli */ 16*0084047dSAppaRao Puli #include <fstream> 17*0084047dSAppaRao Puli #include <regex> 18*0084047dSAppaRao Puli #include "srvcfg_manager.hpp" 19*0084047dSAppaRao Puli 20*0084047dSAppaRao Puli extern std::shared_ptr<boost::asio::deadline_timer> timer; 21*0084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>> 22*0084047dSAppaRao Puli srvMgrObjects; 23*0084047dSAppaRao Puli 24*0084047dSAppaRao Puli namespace phosphor 25*0084047dSAppaRao Puli { 26*0084047dSAppaRao Puli namespace service 27*0084047dSAppaRao Puli { 28*0084047dSAppaRao Puli 29*0084047dSAppaRao Puli static constexpr const char *overrideConfFileName = "override.conf"; 30*0084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds 31*0084047dSAppaRao Puli 32*0084047dSAppaRao Puli static constexpr const char *systemd1UnitBasePath = 33*0084047dSAppaRao Puli "/org/freedesktop/systemd1/unit/"; 34*0084047dSAppaRao Puli static constexpr const char *systemdOverrideUnitBasePath = 35*0084047dSAppaRao Puli "/etc/systemd/system/"; 36*0084047dSAppaRao Puli 37*0084047dSAppaRao Puli void ServiceConfig::syncWithSystemD1Properties() 38*0084047dSAppaRao Puli { 39*0084047dSAppaRao Puli // Read systemd1 socket/service property and load. 40*0084047dSAppaRao Puli conn->async_method_call( 41*0084047dSAppaRao Puli [this](boost::system::error_code ec, 42*0084047dSAppaRao Puli const sdbusplus::message::variant< 43*0084047dSAppaRao Puli std::vector<std::tuple<std::string, std::string>>> &value) { 44*0084047dSAppaRao Puli if (ec) 45*0084047dSAppaRao Puli { 46*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 47*0084047dSAppaRao Puli "async_method_call error: Failed to get property"); 48*0084047dSAppaRao Puli return; 49*0084047dSAppaRao Puli } 50*0084047dSAppaRao Puli 51*0084047dSAppaRao Puli try 52*0084047dSAppaRao Puli { 53*0084047dSAppaRao Puli auto listenVal = sdbusplus::message::variant_ns::get< 54*0084047dSAppaRao Puli std::vector<std::tuple<std::string, std::string>>>(value); 55*0084047dSAppaRao Puli protocol = std::get<0>(listenVal[0]); 56*0084047dSAppaRao Puli std::string port = std::get<1>(listenVal[0]); 57*0084047dSAppaRao Puli auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1), 58*0084047dSAppaRao Puli nullptr, 10); 59*0084047dSAppaRao Puli if (tmp > std::numeric_limits<uint16_t>::max()) 60*0084047dSAppaRao Puli { 61*0084047dSAppaRao Puli throw std::out_of_range("Out of range"); 62*0084047dSAppaRao Puli } 63*0084047dSAppaRao Puli portNum = tmp; 64*0084047dSAppaRao Puli } 65*0084047dSAppaRao Puli catch (const std::exception &e) 66*0084047dSAppaRao Puli { 67*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 68*0084047dSAppaRao Puli "Exception for port number", 69*0084047dSAppaRao Puli phosphor::logging::entry("WHAT=%s", e.what())); 70*0084047dSAppaRao Puli return; 71*0084047dSAppaRao Puli } 72*0084047dSAppaRao Puli conn->async_method_call( 73*0084047dSAppaRao Puli [](boost::system::error_code ec) { 74*0084047dSAppaRao Puli if (ec) 75*0084047dSAppaRao Puli { 76*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 77*0084047dSAppaRao Puli "async_method_call error: Failed to set property"); 78*0084047dSAppaRao Puli return; 79*0084047dSAppaRao Puli } 80*0084047dSAppaRao Puli }, 81*0084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 82*0084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 83*0084047dSAppaRao Puli "Port", sdbusplus::message::variant<uint16_t>(portNum)); 84*0084047dSAppaRao Puli }, 85*0084047dSAppaRao Puli "org.freedesktop.systemd1", sysDSockObjPath.c_str(), 86*0084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Get", 87*0084047dSAppaRao Puli "org.freedesktop.systemd1.Socket", "Listen"); 88*0084047dSAppaRao Puli 89*0084047dSAppaRao Puli conn->async_method_call( 90*0084047dSAppaRao Puli [this](boost::system::error_code ec, 91*0084047dSAppaRao Puli const sdbusplus::message::variant<std::string> &pValue) { 92*0084047dSAppaRao Puli if (ec) 93*0084047dSAppaRao Puli { 94*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 95*0084047dSAppaRao Puli "async_method_call error: Failed to get property"); 96*0084047dSAppaRao Puli return; 97*0084047dSAppaRao Puli } 98*0084047dSAppaRao Puli 99*0084047dSAppaRao Puli channelList.clear(); 100*0084047dSAppaRao Puli std::istringstream stm( 101*0084047dSAppaRao Puli sdbusplus::message::variant_ns::get<std::string>(pValue)); 102*0084047dSAppaRao Puli std::string token; 103*0084047dSAppaRao Puli while (std::getline(stm, token, ',')) 104*0084047dSAppaRao Puli { 105*0084047dSAppaRao Puli channelList.push_back(token); 106*0084047dSAppaRao Puli } 107*0084047dSAppaRao Puli conn->async_method_call( 108*0084047dSAppaRao Puli [](boost::system::error_code ec) { 109*0084047dSAppaRao Puli if (ec) 110*0084047dSAppaRao Puli { 111*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 112*0084047dSAppaRao Puli "async_method_call error: Failed to set property"); 113*0084047dSAppaRao Puli return; 114*0084047dSAppaRao Puli } 115*0084047dSAppaRao Puli }, 116*0084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 117*0084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 118*0084047dSAppaRao Puli "Channel", 119*0084047dSAppaRao Puli sdbusplus::message::variant<std::vector<std::string>>( 120*0084047dSAppaRao Puli channelList)); 121*0084047dSAppaRao Puli }, 122*0084047dSAppaRao Puli "org.freedesktop.systemd1", sysDSockObjPath.c_str(), 123*0084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Get", 124*0084047dSAppaRao Puli "org.freedesktop.systemd1.Socket", "BindToDevice"); 125*0084047dSAppaRao Puli 126*0084047dSAppaRao Puli std::string srvUnitName(sysDUnitName); 127*0084047dSAppaRao Puli if (srvUnitName == "dropbear") 128*0084047dSAppaRao Puli { 129*0084047dSAppaRao Puli srvUnitName.append("@"); 130*0084047dSAppaRao Puli } 131*0084047dSAppaRao Puli srvUnitName.append(".service"); 132*0084047dSAppaRao Puli conn->async_method_call( 133*0084047dSAppaRao Puli [this](boost::system::error_code ec, const std::string &pValue) { 134*0084047dSAppaRao Puli if (ec) 135*0084047dSAppaRao Puli { 136*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 137*0084047dSAppaRao Puli "async_method_call error: Failed to get property"); 138*0084047dSAppaRao Puli return; 139*0084047dSAppaRao Puli } 140*0084047dSAppaRao Puli stateValue = pValue; 141*0084047dSAppaRao Puli conn->async_method_call( 142*0084047dSAppaRao Puli [](boost::system::error_code ec) { 143*0084047dSAppaRao Puli if (ec) 144*0084047dSAppaRao Puli { 145*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 146*0084047dSAppaRao Puli "async_method_call error: Failed to set property"); 147*0084047dSAppaRao Puli return; 148*0084047dSAppaRao Puli } 149*0084047dSAppaRao Puli }, 150*0084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 151*0084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 152*0084047dSAppaRao Puli "State", sdbusplus::message::variant<std::string>(stateValue)); 153*0084047dSAppaRao Puli }, 154*0084047dSAppaRao Puli "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 155*0084047dSAppaRao Puli "org.freedesktop.systemd1.Manager", "GetUnitFileState", srvUnitName); 156*0084047dSAppaRao Puli 157*0084047dSAppaRao Puli return; 158*0084047dSAppaRao Puli } 159*0084047dSAppaRao Puli 160*0084047dSAppaRao Puli ServiceConfig::ServiceConfig( 161*0084047dSAppaRao Puli sdbusplus::asio::object_server &srv_, 162*0084047dSAppaRao Puli std::shared_ptr<sdbusplus::asio::connection> &conn_, std::string objPath_, 163*0084047dSAppaRao Puli std::string unitName) : 164*0084047dSAppaRao Puli server(srv_), 165*0084047dSAppaRao Puli conn(conn_), objPath(objPath_), sysDUnitName(unitName) 166*0084047dSAppaRao Puli { 167*0084047dSAppaRao Puli std::string socketUnitName(sysDUnitName + ".socket"); 168*0084047dSAppaRao Puli // .socket systemd service files are handled. 169*0084047dSAppaRao Puli // Regular .service only files are ignored. 170*0084047dSAppaRao Puli if (!checkSystemdUnitExist(socketUnitName)) 171*0084047dSAppaRao Puli { 172*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 173*0084047dSAppaRao Puli "Unit doesn't exist.", 174*0084047dSAppaRao Puli phosphor::logging::entry("UNITNAME=%s", socketUnitName.c_str())); 175*0084047dSAppaRao Puli phosphor::logging::elog< 176*0084047dSAppaRao Puli sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 177*0084047dSAppaRao Puli } 178*0084047dSAppaRao Puli 179*0084047dSAppaRao Puli /// Check override socket directory exist, if not create it. 180*0084047dSAppaRao Puli std::experimental::filesystem::path ovrUnitFileDir( 181*0084047dSAppaRao Puli systemdOverrideUnitBasePath); 182*0084047dSAppaRao Puli ovrUnitFileDir += socketUnitName; 183*0084047dSAppaRao Puli ovrUnitFileDir += ".d"; 184*0084047dSAppaRao Puli if (!std::experimental::filesystem::exists(ovrUnitFileDir)) 185*0084047dSAppaRao Puli { 186*0084047dSAppaRao Puli if (!std::experimental::filesystem::create_directories(ovrUnitFileDir)) 187*0084047dSAppaRao Puli { 188*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 189*0084047dSAppaRao Puli "Unable to create the directory.", 190*0084047dSAppaRao Puli phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str())); 191*0084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 192*0084047dSAppaRao Puli Error::InternalFailure>(); 193*0084047dSAppaRao Puli } 194*0084047dSAppaRao Puli } 195*0084047dSAppaRao Puli 196*0084047dSAppaRao Puli /* Store require info locally */ 197*0084047dSAppaRao Puli unitSocketFilePath = std::string(ovrUnitFileDir); 198*0084047dSAppaRao Puli 199*0084047dSAppaRao Puli sysDSockObjPath = systemd1UnitBasePath; 200*0084047dSAppaRao Puli sysDSockObjPath.append( 201*0084047dSAppaRao Puli std::regex_replace(sysDUnitName, std::regex("-"), "_2d")); 202*0084047dSAppaRao Puli sysDSockObjPath.append("_2esocket"); 203*0084047dSAppaRao Puli 204*0084047dSAppaRao Puli // Adds interface, object and Properties.... 205*0084047dSAppaRao Puli registerProperties(); 206*0084047dSAppaRao Puli 207*0084047dSAppaRao Puli syncWithSystemD1Properties(); 208*0084047dSAppaRao Puli 209*0084047dSAppaRao Puli updatedFlag = 0; 210*0084047dSAppaRao Puli return; 211*0084047dSAppaRao Puli } 212*0084047dSAppaRao Puli 213*0084047dSAppaRao Puli void ServiceConfig::applySystemDServiceConfig() 214*0084047dSAppaRao Puli { 215*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::INFO>( 216*0084047dSAppaRao Puli "Applying new settings.", 217*0084047dSAppaRao Puli phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 218*0084047dSAppaRao Puli if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::channel)) | 219*0084047dSAppaRao Puli (1 << static_cast<uint8_t>(UpdatedProp::port)))) 220*0084047dSAppaRao Puli { 221*0084047dSAppaRao Puli // Create override config file and write data. 222*0084047dSAppaRao Puli std::string ovrCfgFile{unitSocketFilePath + "/" + overrideConfFileName}; 223*0084047dSAppaRao Puli std::string tmpFile{ovrCfgFile + "_tmp"}; 224*0084047dSAppaRao Puli std::ofstream cfgFile(tmpFile, std::ios::out); 225*0084047dSAppaRao Puli if (!cfgFile.good()) 226*0084047dSAppaRao Puli { 227*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 228*0084047dSAppaRao Puli "Failed to open override.conf_tmp file"); 229*0084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 230*0084047dSAppaRao Puli Error::InternalFailure>(); 231*0084047dSAppaRao Puli } 232*0084047dSAppaRao Puli 233*0084047dSAppaRao Puli // Write the socket header 234*0084047dSAppaRao Puli cfgFile << "[Socket]\n"; 235*0084047dSAppaRao Puli // Listen 236*0084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" 237*0084047dSAppaRao Puli << "\n"; 238*0084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" << portNum << "\n"; 239*0084047dSAppaRao Puli // BindToDevice 240*0084047dSAppaRao Puli bool firstElement = true; 241*0084047dSAppaRao Puli cfgFile << "BindToDevice="; 242*0084047dSAppaRao Puli for (const auto &it : channelList) 243*0084047dSAppaRao Puli { 244*0084047dSAppaRao Puli if (firstElement) 245*0084047dSAppaRao Puli { 246*0084047dSAppaRao Puli cfgFile << it; 247*0084047dSAppaRao Puli firstElement = false; 248*0084047dSAppaRao Puli } 249*0084047dSAppaRao Puli else 250*0084047dSAppaRao Puli { 251*0084047dSAppaRao Puli cfgFile << "," << it; 252*0084047dSAppaRao Puli } 253*0084047dSAppaRao Puli } 254*0084047dSAppaRao Puli cfgFile.close(); 255*0084047dSAppaRao Puli 256*0084047dSAppaRao Puli if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0) 257*0084047dSAppaRao Puli { 258*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 259*0084047dSAppaRao Puli "Failed to rename tmp file as override.conf"); 260*0084047dSAppaRao Puli std::remove(tmpFile.c_str()); 261*0084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 262*0084047dSAppaRao Puli Error::InternalFailure>(); 263*0084047dSAppaRao Puli } 264*0084047dSAppaRao Puli 265*0084047dSAppaRao Puli // Systemd forcing explicit socket stop before reload...! 266*0084047dSAppaRao Puli std::string socketUnitName(sysDUnitName + ".socket"); 267*0084047dSAppaRao Puli systemdUnitAction(conn, socketUnitName, sysdActionStopUnit); 268*0084047dSAppaRao Puli 269*0084047dSAppaRao Puli std::string srvUnitName(sysDUnitName + ".service"); 270*0084047dSAppaRao Puli systemdUnitAction(conn, srvUnitName, sysdActionStopUnit); 271*0084047dSAppaRao Puli 272*0084047dSAppaRao Puli // Perform daemon reload to read new settings 273*0084047dSAppaRao Puli systemdDaemonReload(conn); 274*0084047dSAppaRao Puli 275*0084047dSAppaRao Puli // Restart the unit 276*0084047dSAppaRao Puli systemdUnitAction(conn, socketUnitName, sysdActionStartUnit); 277*0084047dSAppaRao Puli systemdUnitAction(conn, srvUnitName, sysdActionStartUnit); 278*0084047dSAppaRao Puli } 279*0084047dSAppaRao Puli 280*0084047dSAppaRao Puli if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state))) 281*0084047dSAppaRao Puli { 282*0084047dSAppaRao Puli if ((stateValue == "enabled") || (stateValue == "disabled")) 283*0084047dSAppaRao Puli { 284*0084047dSAppaRao Puli systemdUnitFileStateChange(conn, sysDUnitName, stateValue); 285*0084047dSAppaRao Puli } 286*0084047dSAppaRao Puli } 287*0084047dSAppaRao Puli 288*0084047dSAppaRao Puli // Reset the flag 289*0084047dSAppaRao Puli updatedFlag = 0; 290*0084047dSAppaRao Puli 291*0084047dSAppaRao Puli // All done. Lets reload the properties which are applied on systemd1. 292*0084047dSAppaRao Puli // TODO: We need to capture the service restart signal and reload data 293*0084047dSAppaRao Puli // inside the signal handler. So that we can update the service properties 294*0084047dSAppaRao Puli // modified, outside of this service as well. 295*0084047dSAppaRao Puli syncWithSystemD1Properties(); 296*0084047dSAppaRao Puli 297*0084047dSAppaRao Puli return; 298*0084047dSAppaRao Puli } 299*0084047dSAppaRao Puli 300*0084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer() 301*0084047dSAppaRao Puli { 302*0084047dSAppaRao Puli timer->expires_from_now(boost::posix_time::seconds(restartTimeout)); 303*0084047dSAppaRao Puli timer->async_wait([this](const boost::system::error_code &ec) { 304*0084047dSAppaRao Puli if (ec == boost::asio::error::operation_aborted) 305*0084047dSAppaRao Puli { 306*0084047dSAppaRao Puli // Timer reset. 307*0084047dSAppaRao Puli return; 308*0084047dSAppaRao Puli } 309*0084047dSAppaRao Puli else if (ec) 310*0084047dSAppaRao Puli { 311*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 312*0084047dSAppaRao Puli "async wait error."); 313*0084047dSAppaRao Puli return; 314*0084047dSAppaRao Puli } 315*0084047dSAppaRao Puli for (auto &srvMgrObj : srvMgrObjects) 316*0084047dSAppaRao Puli { 317*0084047dSAppaRao Puli auto &srvObj = srvMgrObj.second; 318*0084047dSAppaRao Puli if (srvObj->updatedFlag) 319*0084047dSAppaRao Puli { 320*0084047dSAppaRao Puli srvObj->applySystemDServiceConfig(); 321*0084047dSAppaRao Puli } 322*0084047dSAppaRao Puli } 323*0084047dSAppaRao Puli }); 324*0084047dSAppaRao Puli } 325*0084047dSAppaRao Puli 326*0084047dSAppaRao Puli void ServiceConfig::registerProperties() 327*0084047dSAppaRao Puli { 328*0084047dSAppaRao Puli std::shared_ptr<sdbusplus::asio::dbus_interface> iface = 329*0084047dSAppaRao Puli server.add_interface(objPath, serviceConfigIntfName); 330*0084047dSAppaRao Puli 331*0084047dSAppaRao Puli iface->register_property( 332*0084047dSAppaRao Puli "Port", portNum, [this](const uint16_t &req, uint16_t &res) { 333*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 334*0084047dSAppaRao Puli " Inside register_property"); 335*0084047dSAppaRao Puli if (req == res) 336*0084047dSAppaRao Puli { 337*0084047dSAppaRao Puli return 1; 338*0084047dSAppaRao Puli } 339*0084047dSAppaRao Puli portNum = req; 340*0084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::port)); 341*0084047dSAppaRao Puli startServiceRestartTimer(); 342*0084047dSAppaRao Puli res = req; 343*0084047dSAppaRao Puli return 1; 344*0084047dSAppaRao Puli }); 345*0084047dSAppaRao Puli 346*0084047dSAppaRao Puli iface->register_property( 347*0084047dSAppaRao Puli "Channel", channelList, 348*0084047dSAppaRao Puli [this](const std::vector<std::string> &req, 349*0084047dSAppaRao Puli std::vector<std::string> &res) { 350*0084047dSAppaRao Puli if (req == res) 351*0084047dSAppaRao Puli { 352*0084047dSAppaRao Puli return 1; 353*0084047dSAppaRao Puli } 354*0084047dSAppaRao Puli channelList.clear(); 355*0084047dSAppaRao Puli std::copy(req.begin(), req.end(), back_inserter(channelList)); 356*0084047dSAppaRao Puli 357*0084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::channel)); 358*0084047dSAppaRao Puli startServiceRestartTimer(); 359*0084047dSAppaRao Puli res = req; 360*0084047dSAppaRao Puli return 1; 361*0084047dSAppaRao Puli }); 362*0084047dSAppaRao Puli 363*0084047dSAppaRao Puli iface->register_property( 364*0084047dSAppaRao Puli "State", stateValue, [this](const std::string &req, std::string &res) { 365*0084047dSAppaRao Puli if (req == res) 366*0084047dSAppaRao Puli { 367*0084047dSAppaRao Puli return 1; 368*0084047dSAppaRao Puli } 369*0084047dSAppaRao Puli if ((req != "enabled") && (req != "disabled") && (req != "static")) 370*0084047dSAppaRao Puli { 371*0084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 372*0084047dSAppaRao Puli "Invalid value specified"); 373*0084047dSAppaRao Puli return -EINVAL; 374*0084047dSAppaRao Puli } 375*0084047dSAppaRao Puli stateValue = req; 376*0084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::state)); 377*0084047dSAppaRao Puli startServiceRestartTimer(); 378*0084047dSAppaRao Puli res = req; 379*0084047dSAppaRao Puli return 1; 380*0084047dSAppaRao Puli }); 381*0084047dSAppaRao Puli 382*0084047dSAppaRao Puli iface->initialize(); 383*0084047dSAppaRao Puli return; 384*0084047dSAppaRao Puli } 385*0084047dSAppaRao Puli 386*0084047dSAppaRao Puli } // namespace service 387*0084047dSAppaRao Puli } // namespace phosphor 388