xref: /openbmc/service-config-manager/src/srvcfg_manager.cpp (revision 0084047d008fd0ac36f09a232f67ff2fc5314b53)
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