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> 180084047dSAppaRao Puli #include "srvcfg_manager.hpp" 190084047dSAppaRao Puli 200084047dSAppaRao Puli extern std::shared_ptr<boost::asio::deadline_timer> timer; 210084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>> 220084047dSAppaRao Puli srvMgrObjects; 230084047dSAppaRao Puli 240084047dSAppaRao Puli namespace phosphor 250084047dSAppaRao Puli { 260084047dSAppaRao Puli namespace service 270084047dSAppaRao Puli { 280084047dSAppaRao Puli 290084047dSAppaRao Puli static constexpr const char *overrideConfFileName = "override.conf"; 300084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds 310084047dSAppaRao Puli 320084047dSAppaRao Puli static constexpr const char *systemd1UnitBasePath = 330084047dSAppaRao Puli "/org/freedesktop/systemd1/unit/"; 340084047dSAppaRao Puli static constexpr const char *systemdOverrideUnitBasePath = 350084047dSAppaRao Puli "/etc/systemd/system/"; 360084047dSAppaRao Puli 370084047dSAppaRao Puli void ServiceConfig::syncWithSystemD1Properties() 380084047dSAppaRao Puli { 390084047dSAppaRao Puli // Read systemd1 socket/service property and load. 400084047dSAppaRao Puli conn->async_method_call( 410084047dSAppaRao Puli [this](boost::system::error_code ec, 420084047dSAppaRao Puli const sdbusplus::message::variant< 430084047dSAppaRao Puli std::vector<std::tuple<std::string, std::string>>> &value) { 440084047dSAppaRao Puli if (ec) 450084047dSAppaRao Puli { 460084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 470084047dSAppaRao Puli "async_method_call error: Failed to get property"); 480084047dSAppaRao Puli return; 490084047dSAppaRao Puli } 500084047dSAppaRao Puli 510084047dSAppaRao Puli try 520084047dSAppaRao Puli { 530084047dSAppaRao Puli auto listenVal = sdbusplus::message::variant_ns::get< 540084047dSAppaRao Puli std::vector<std::tuple<std::string, std::string>>>(value); 550084047dSAppaRao Puli protocol = std::get<0>(listenVal[0]); 560084047dSAppaRao Puli std::string port = std::get<1>(listenVal[0]); 570084047dSAppaRao Puli auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1), 580084047dSAppaRao Puli nullptr, 10); 590084047dSAppaRao Puli if (tmp > std::numeric_limits<uint16_t>::max()) 600084047dSAppaRao Puli { 610084047dSAppaRao Puli throw std::out_of_range("Out of range"); 620084047dSAppaRao Puli } 630084047dSAppaRao Puli portNum = tmp; 640084047dSAppaRao Puli } 650084047dSAppaRao Puli catch (const std::exception &e) 660084047dSAppaRao Puli { 670084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 680084047dSAppaRao Puli "Exception for port number", 690084047dSAppaRao Puli phosphor::logging::entry("WHAT=%s", e.what())); 700084047dSAppaRao Puli return; 710084047dSAppaRao Puli } 720084047dSAppaRao Puli conn->async_method_call( 730084047dSAppaRao Puli [](boost::system::error_code ec) { 740084047dSAppaRao Puli if (ec) 750084047dSAppaRao Puli { 760084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 770084047dSAppaRao Puli "async_method_call error: Failed to set property"); 780084047dSAppaRao Puli return; 790084047dSAppaRao Puli } 800084047dSAppaRao Puli }, 810084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 820084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 830084047dSAppaRao Puli "Port", sdbusplus::message::variant<uint16_t>(portNum)); 840084047dSAppaRao Puli }, 850084047dSAppaRao Puli "org.freedesktop.systemd1", sysDSockObjPath.c_str(), 860084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Get", 870084047dSAppaRao Puli "org.freedesktop.systemd1.Socket", "Listen"); 880084047dSAppaRao Puli 890084047dSAppaRao Puli conn->async_method_call( 900084047dSAppaRao Puli [this](boost::system::error_code ec, 910084047dSAppaRao Puli const sdbusplus::message::variant<std::string> &pValue) { 920084047dSAppaRao Puli if (ec) 930084047dSAppaRao Puli { 940084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 950084047dSAppaRao Puli "async_method_call error: Failed to get property"); 960084047dSAppaRao Puli return; 970084047dSAppaRao Puli } 980084047dSAppaRao Puli 990084047dSAppaRao Puli channelList.clear(); 1000084047dSAppaRao Puli std::istringstream stm( 1010084047dSAppaRao Puli sdbusplus::message::variant_ns::get<std::string>(pValue)); 1020084047dSAppaRao Puli std::string token; 1030084047dSAppaRao Puli while (std::getline(stm, token, ',')) 1040084047dSAppaRao Puli { 1050084047dSAppaRao Puli channelList.push_back(token); 1060084047dSAppaRao Puli } 1070084047dSAppaRao Puli conn->async_method_call( 1080084047dSAppaRao Puli [](boost::system::error_code ec) { 1090084047dSAppaRao Puli if (ec) 1100084047dSAppaRao Puli { 1110084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1120084047dSAppaRao Puli "async_method_call error: Failed to set property"); 1130084047dSAppaRao Puli return; 1140084047dSAppaRao Puli } 1150084047dSAppaRao Puli }, 1160084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 1170084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 1180084047dSAppaRao Puli "Channel", 1190084047dSAppaRao Puli sdbusplus::message::variant<std::vector<std::string>>( 1200084047dSAppaRao Puli channelList)); 1210084047dSAppaRao Puli }, 1220084047dSAppaRao Puli "org.freedesktop.systemd1", sysDSockObjPath.c_str(), 1230084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Get", 1240084047dSAppaRao Puli "org.freedesktop.systemd1.Socket", "BindToDevice"); 1250084047dSAppaRao Puli 1260084047dSAppaRao Puli std::string srvUnitName(sysDUnitName); 1270084047dSAppaRao Puli if (srvUnitName == "dropbear") 1280084047dSAppaRao Puli { 129*e55cfd6eSAppaRao Puli // Dropbear service expects template arguments. 1300084047dSAppaRao Puli srvUnitName.append("@"); 1310084047dSAppaRao Puli } 1320084047dSAppaRao Puli srvUnitName.append(".service"); 1330084047dSAppaRao Puli conn->async_method_call( 1340084047dSAppaRao Puli [this](boost::system::error_code ec, const std::string &pValue) { 1350084047dSAppaRao Puli if (ec) 1360084047dSAppaRao Puli { 1370084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1380084047dSAppaRao Puli "async_method_call error: Failed to get property"); 1390084047dSAppaRao Puli return; 1400084047dSAppaRao Puli } 141*e55cfd6eSAppaRao Puli if ((pValue == "enabled") || (pValue == "static") || 142*e55cfd6eSAppaRao Puli (pValue == "unmasked")) 143*e55cfd6eSAppaRao Puli { 144*e55cfd6eSAppaRao Puli stateValue = "enabled"; 145*e55cfd6eSAppaRao Puli } 146*e55cfd6eSAppaRao Puli else if ((pValue == "disabled") || (pValue == "masked")) 147*e55cfd6eSAppaRao Puli { 148*e55cfd6eSAppaRao Puli stateValue = "disabled"; 149*e55cfd6eSAppaRao Puli } 1500084047dSAppaRao Puli conn->async_method_call( 1510084047dSAppaRao Puli [](boost::system::error_code ec) { 1520084047dSAppaRao Puli if (ec) 1530084047dSAppaRao Puli { 1540084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1550084047dSAppaRao Puli "async_method_call error: Failed to set property"); 1560084047dSAppaRao Puli return; 1570084047dSAppaRao Puli } 1580084047dSAppaRao Puli }, 1590084047dSAppaRao Puli serviceConfigSrvName, objPath.c_str(), 1600084047dSAppaRao Puli "org.freedesktop.DBus.Properties", "Set", serviceConfigIntfName, 1610084047dSAppaRao Puli "State", sdbusplus::message::variant<std::string>(stateValue)); 1620084047dSAppaRao Puli }, 1630084047dSAppaRao Puli "org.freedesktop.systemd1", "/org/freedesktop/systemd1", 1640084047dSAppaRao Puli "org.freedesktop.systemd1.Manager", "GetUnitFileState", srvUnitName); 1650084047dSAppaRao Puli 1660084047dSAppaRao Puli return; 1670084047dSAppaRao Puli } 1680084047dSAppaRao Puli 1690084047dSAppaRao Puli ServiceConfig::ServiceConfig( 1700084047dSAppaRao Puli sdbusplus::asio::object_server &srv_, 1710084047dSAppaRao Puli std::shared_ptr<sdbusplus::asio::connection> &conn_, std::string objPath_, 1720084047dSAppaRao Puli std::string unitName) : 1730084047dSAppaRao Puli server(srv_), 1740084047dSAppaRao Puli conn(conn_), objPath(objPath_), sysDUnitName(unitName) 1750084047dSAppaRao Puli { 1760084047dSAppaRao Puli std::string socketUnitName(sysDUnitName + ".socket"); 1770084047dSAppaRao Puli // .socket systemd service files are handled. 1780084047dSAppaRao Puli // Regular .service only files are ignored. 1790084047dSAppaRao Puli if (!checkSystemdUnitExist(socketUnitName)) 1800084047dSAppaRao Puli { 1810084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1820084047dSAppaRao Puli "Unit doesn't exist.", 1830084047dSAppaRao Puli phosphor::logging::entry("UNITNAME=%s", socketUnitName.c_str())); 1840084047dSAppaRao Puli phosphor::logging::elog< 1850084047dSAppaRao Puli sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure>(); 1860084047dSAppaRao Puli } 1870084047dSAppaRao Puli 1880084047dSAppaRao Puli /// Check override socket directory exist, if not create it. 1890084047dSAppaRao Puli std::experimental::filesystem::path ovrUnitFileDir( 1900084047dSAppaRao Puli systemdOverrideUnitBasePath); 1910084047dSAppaRao Puli ovrUnitFileDir += socketUnitName; 1920084047dSAppaRao Puli ovrUnitFileDir += ".d"; 1930084047dSAppaRao Puli if (!std::experimental::filesystem::exists(ovrUnitFileDir)) 1940084047dSAppaRao Puli { 1950084047dSAppaRao Puli if (!std::experimental::filesystem::create_directories(ovrUnitFileDir)) 1960084047dSAppaRao Puli { 1970084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 1980084047dSAppaRao Puli "Unable to create the directory.", 1990084047dSAppaRao Puli phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str())); 2000084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2010084047dSAppaRao Puli Error::InternalFailure>(); 2020084047dSAppaRao Puli } 2030084047dSAppaRao Puli } 2040084047dSAppaRao Puli 2050084047dSAppaRao Puli /* Store require info locally */ 2060084047dSAppaRao Puli unitSocketFilePath = std::string(ovrUnitFileDir); 2070084047dSAppaRao Puli 2080084047dSAppaRao Puli sysDSockObjPath = systemd1UnitBasePath; 2090084047dSAppaRao Puli sysDSockObjPath.append( 2100084047dSAppaRao Puli std::regex_replace(sysDUnitName, std::regex("-"), "_2d")); 2110084047dSAppaRao Puli sysDSockObjPath.append("_2esocket"); 2120084047dSAppaRao Puli 2130084047dSAppaRao Puli // Adds interface, object and Properties.... 2140084047dSAppaRao Puli registerProperties(); 2150084047dSAppaRao Puli 2160084047dSAppaRao Puli syncWithSystemD1Properties(); 2170084047dSAppaRao Puli 2180084047dSAppaRao Puli updatedFlag = 0; 2190084047dSAppaRao Puli return; 2200084047dSAppaRao Puli } 2210084047dSAppaRao Puli 2220084047dSAppaRao Puli void ServiceConfig::applySystemDServiceConfig() 2230084047dSAppaRao Puli { 224*e55cfd6eSAppaRao Puli if (updatedFlag) 225*e55cfd6eSAppaRao Puli { 226*e55cfd6eSAppaRao Puli // No updates. Just return. 227*e55cfd6eSAppaRao Puli return; 228*e55cfd6eSAppaRao Puli } 229*e55cfd6eSAppaRao Puli 2300084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::INFO>( 2310084047dSAppaRao Puli "Applying new settings.", 2320084047dSAppaRao Puli phosphor::logging::entry("OBJPATH=%s", objPath.c_str())); 2330084047dSAppaRao Puli if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::channel)) | 2340084047dSAppaRao Puli (1 << static_cast<uint8_t>(UpdatedProp::port)))) 2350084047dSAppaRao Puli { 2360084047dSAppaRao Puli // Create override config file and write data. 2370084047dSAppaRao Puli std::string ovrCfgFile{unitSocketFilePath + "/" + overrideConfFileName}; 2380084047dSAppaRao Puli std::string tmpFile{ovrCfgFile + "_tmp"}; 2390084047dSAppaRao Puli std::ofstream cfgFile(tmpFile, std::ios::out); 2400084047dSAppaRao Puli if (!cfgFile.good()) 2410084047dSAppaRao Puli { 2420084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2430084047dSAppaRao Puli "Failed to open override.conf_tmp file"); 2440084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2450084047dSAppaRao Puli Error::InternalFailure>(); 2460084047dSAppaRao Puli } 2470084047dSAppaRao Puli 2480084047dSAppaRao Puli // Write the socket header 2490084047dSAppaRao Puli cfgFile << "[Socket]\n"; 2500084047dSAppaRao Puli // Listen 2510084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" 2520084047dSAppaRao Puli << "\n"; 2530084047dSAppaRao Puli cfgFile << "Listen" << protocol << "=" << portNum << "\n"; 2540084047dSAppaRao Puli // BindToDevice 2550084047dSAppaRao Puli bool firstElement = true; 2560084047dSAppaRao Puli cfgFile << "BindToDevice="; 2570084047dSAppaRao Puli for (const auto &it : channelList) 2580084047dSAppaRao Puli { 2590084047dSAppaRao Puli if (firstElement) 2600084047dSAppaRao Puli { 2610084047dSAppaRao Puli cfgFile << it; 2620084047dSAppaRao Puli firstElement = false; 2630084047dSAppaRao Puli } 2640084047dSAppaRao Puli else 2650084047dSAppaRao Puli { 2660084047dSAppaRao Puli cfgFile << "," << it; 2670084047dSAppaRao Puli } 2680084047dSAppaRao Puli } 2690084047dSAppaRao Puli cfgFile.close(); 2700084047dSAppaRao Puli 2710084047dSAppaRao Puli if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0) 2720084047dSAppaRao Puli { 2730084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 2740084047dSAppaRao Puli "Failed to rename tmp file as override.conf"); 2750084047dSAppaRao Puli std::remove(tmpFile.c_str()); 2760084047dSAppaRao Puli phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common:: 2770084047dSAppaRao Puli Error::InternalFailure>(); 2780084047dSAppaRao Puli } 279*e55cfd6eSAppaRao Puli } 2800084047dSAppaRao Puli 2810084047dSAppaRao Puli std::string socketUnitName(sysDUnitName + ".socket"); 282*e55cfd6eSAppaRao Puli std::string srvUnitName(sysDUnitName); 283*e55cfd6eSAppaRao Puli if (srvUnitName == "dropbear") 284*e55cfd6eSAppaRao Puli { 285*e55cfd6eSAppaRao Puli // Dropbear service expects template arguments. 286*e55cfd6eSAppaRao Puli // Todo: Unit action for service, fails with error 287*e55cfd6eSAppaRao Puli // "missing the instance name". Needs to implement 288*e55cfd6eSAppaRao Puli // getting all running instances and use it. This 289*e55cfd6eSAppaRao Puli // impact runtime but works fine during reboot. 290*e55cfd6eSAppaRao Puli srvUnitName.append("@"); 291*e55cfd6eSAppaRao Puli } 292*e55cfd6eSAppaRao Puli srvUnitName.append(".service"); 293*e55cfd6eSAppaRao Puli // Stop the running service in below scenarios. 294*e55cfd6eSAppaRao Puli // 1. State changed from "enabled" to "disabled" 295*e55cfd6eSAppaRao Puli // 2. No change in state and existing stateValue is 296*e55cfd6eSAppaRao Puli // "enabled" and there is change in other properties. 297*e55cfd6eSAppaRao Puli if (((stateValue == "disabled") && 298*e55cfd6eSAppaRao Puli (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state)))) || 299*e55cfd6eSAppaRao Puli (!(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state))) && 300*e55cfd6eSAppaRao Puli (stateValue == "enabled") && (updatedFlag))) 301*e55cfd6eSAppaRao Puli { 302*e55cfd6eSAppaRao Puli systemdUnitAction(conn, socketUnitName, "StopUnit"); 303*e55cfd6eSAppaRao Puli systemdUnitAction(conn, srvUnitName, "StopUnit"); 3040084047dSAppaRao Puli } 3050084047dSAppaRao Puli 3060084047dSAppaRao Puli if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::state))) 3070084047dSAppaRao Puli { 308*e55cfd6eSAppaRao Puli std::vector<std::string> unitFiles = {socketUnitName, srvUnitName}; 309*e55cfd6eSAppaRao Puli systemdUnitFilesStateChange(conn, unitFiles, stateValue); 3100084047dSAppaRao Puli } 311*e55cfd6eSAppaRao Puli 312*e55cfd6eSAppaRao Puli // Perform daemon reload to read new settings 313*e55cfd6eSAppaRao Puli systemdDaemonReload(conn); 314*e55cfd6eSAppaRao Puli 315*e55cfd6eSAppaRao Puli if (stateValue == "enabled") 316*e55cfd6eSAppaRao Puli { 317*e55cfd6eSAppaRao Puli // Restart the socket 318*e55cfd6eSAppaRao Puli systemdUnitAction(conn, socketUnitName, "StartUnit"); 3190084047dSAppaRao Puli } 3200084047dSAppaRao Puli 3210084047dSAppaRao Puli // Reset the flag 3220084047dSAppaRao Puli updatedFlag = 0; 3230084047dSAppaRao Puli 3240084047dSAppaRao Puli // All done. Lets reload the properties which are applied on systemd1. 3250084047dSAppaRao Puli // TODO: We need to capture the service restart signal and reload data 326*e55cfd6eSAppaRao Puli // inside the signal handler. So that we can update the service 327*e55cfd6eSAppaRao Puli // properties modified, outside of this service as well. 3280084047dSAppaRao Puli syncWithSystemD1Properties(); 3290084047dSAppaRao Puli 3300084047dSAppaRao Puli return; 3310084047dSAppaRao Puli } 3320084047dSAppaRao Puli 3330084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer() 3340084047dSAppaRao Puli { 3350084047dSAppaRao Puli timer->expires_from_now(boost::posix_time::seconds(restartTimeout)); 3360084047dSAppaRao Puli timer->async_wait([this](const boost::system::error_code &ec) { 3370084047dSAppaRao Puli if (ec == boost::asio::error::operation_aborted) 3380084047dSAppaRao Puli { 3390084047dSAppaRao Puli // Timer reset. 3400084047dSAppaRao Puli return; 3410084047dSAppaRao Puli } 3420084047dSAppaRao Puli else if (ec) 3430084047dSAppaRao Puli { 3440084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 3450084047dSAppaRao Puli "async wait error."); 3460084047dSAppaRao Puli return; 3470084047dSAppaRao Puli } 3480084047dSAppaRao Puli for (auto &srvMgrObj : srvMgrObjects) 3490084047dSAppaRao Puli { 3500084047dSAppaRao Puli auto &srvObj = srvMgrObj.second; 3510084047dSAppaRao Puli if (srvObj->updatedFlag) 3520084047dSAppaRao Puli { 3530084047dSAppaRao Puli srvObj->applySystemDServiceConfig(); 3540084047dSAppaRao Puli } 3550084047dSAppaRao Puli } 3560084047dSAppaRao Puli }); 3570084047dSAppaRao Puli } 3580084047dSAppaRao Puli 3590084047dSAppaRao Puli void ServiceConfig::registerProperties() 3600084047dSAppaRao Puli { 3610084047dSAppaRao Puli std::shared_ptr<sdbusplus::asio::dbus_interface> iface = 3620084047dSAppaRao Puli server.add_interface(objPath, serviceConfigIntfName); 3630084047dSAppaRao Puli 3640084047dSAppaRao Puli iface->register_property( 3650084047dSAppaRao Puli "Port", portNum, [this](const uint16_t &req, uint16_t &res) { 3660084047dSAppaRao Puli if (req == res) 3670084047dSAppaRao Puli { 3680084047dSAppaRao Puli return 1; 3690084047dSAppaRao Puli } 3700084047dSAppaRao Puli portNum = req; 3710084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::port)); 3720084047dSAppaRao Puli startServiceRestartTimer(); 3730084047dSAppaRao Puli res = req; 3740084047dSAppaRao Puli return 1; 3750084047dSAppaRao Puli }); 3760084047dSAppaRao Puli 3770084047dSAppaRao Puli iface->register_property( 3780084047dSAppaRao Puli "Channel", channelList, 3790084047dSAppaRao Puli [this](const std::vector<std::string> &req, 3800084047dSAppaRao Puli std::vector<std::string> &res) { 3810084047dSAppaRao Puli if (req == res) 3820084047dSAppaRao Puli { 3830084047dSAppaRao Puli return 1; 3840084047dSAppaRao Puli } 3850084047dSAppaRao Puli channelList.clear(); 3860084047dSAppaRao Puli std::copy(req.begin(), req.end(), back_inserter(channelList)); 3870084047dSAppaRao Puli 3880084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::channel)); 3890084047dSAppaRao Puli startServiceRestartTimer(); 3900084047dSAppaRao Puli res = req; 3910084047dSAppaRao Puli return 1; 3920084047dSAppaRao Puli }); 3930084047dSAppaRao Puli 3940084047dSAppaRao Puli iface->register_property( 3950084047dSAppaRao Puli "State", stateValue, [this](const std::string &req, std::string &res) { 3960084047dSAppaRao Puli if (req == res) 3970084047dSAppaRao Puli { 3980084047dSAppaRao Puli return 1; 3990084047dSAppaRao Puli } 400*e55cfd6eSAppaRao Puli if ((req != "enabled") && (req != "disabled")) 4010084047dSAppaRao Puli { 4020084047dSAppaRao Puli phosphor::logging::log<phosphor::logging::level::ERR>( 4030084047dSAppaRao Puli "Invalid value specified"); 4040084047dSAppaRao Puli return -EINVAL; 4050084047dSAppaRao Puli } 4060084047dSAppaRao Puli stateValue = req; 4070084047dSAppaRao Puli updatedFlag |= (1 << static_cast<uint8_t>(UpdatedProp::state)); 4080084047dSAppaRao Puli startServiceRestartTimer(); 4090084047dSAppaRao Puli res = req; 4100084047dSAppaRao Puli return 1; 4110084047dSAppaRao Puli }); 4120084047dSAppaRao Puli 4130084047dSAppaRao Puli iface->initialize(); 4140084047dSAppaRao Puli return; 4150084047dSAppaRao Puli } 4160084047dSAppaRao Puli 4170084047dSAppaRao Puli } // namespace service 4180084047dSAppaRao Puli } // namespace phosphor 419