xref: /openbmc/service-config-manager/src/srvcfg_manager.cpp (revision c828db702208df9fccd96f8bef036e3f32012bcd)
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "srvcfg_manager.hpp"
17 
18 #include <boost/asio/detached.hpp>
19 #include <boost/asio/spawn.hpp>
20 
21 #ifdef USB_CODE_UPDATE
22 #include <cereal/archives/json.hpp>
23 #include <cereal/types/tuple.hpp>
24 #include <cereal/types/unordered_map.hpp>
25 
26 #include <cstdio>
27 #endif
28 
29 #include <fstream>
30 #include <regex>
31 
32 extern std::unique_ptr<boost::asio::steady_timer> timer;
33 extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
34     srvMgrObjects;
35 static bool updateInProgress = false;
36 
37 namespace phosphor
38 {
39 namespace service
40 {
41 
42 static constexpr const char* overrideConfFileName = "override.conf";
43 static constexpr const size_t restartTimeout = 15; // seconds
44 
45 static constexpr const char* systemd1UnitBasePath =
46     "/org/freedesktop/systemd1/unit/";
47 static constexpr const char* systemdOverrideUnitBasePath =
48     "/etc/systemd/system/";
49 
50 #ifdef USB_CODE_UPDATE
51 static constexpr const char* usbCodeUpdateStateFilePath =
52     "/var/lib/srvcfg_manager";
53 static constexpr const char* usbCodeUpdateStateFile =
54     "/var/lib/srvcfg_manager/usb-code-update-state";
55 static constexpr const char* emptyUsbCodeUpdateRulesFile =
56     "/etc/udev/rules.d/70-bmc-usb.rules";
57 
58 using UsbCodeUpdateStateMap = std::unordered_map<std::string, bool>;
59 
setUSBCodeUpdateState(const bool & state)60 void ServiceConfig::setUSBCodeUpdateState(const bool& state)
61 {
62     // Enable usb code update
63     if (state)
64     {
65         if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
66         {
67             lg2::info("Enable usb code update");
68             std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
69         }
70         return;
71     }
72 
73     // Disable usb code update
74     if (std::filesystem::exists(emptyUsbCodeUpdateRulesFile))
75     {
76         std::filesystem::remove(emptyUsbCodeUpdateRulesFile);
77     }
78     std::error_code ec;
79     std::filesystem::create_symlink("/dev/null", emptyUsbCodeUpdateRulesFile,
80                                     ec);
81     if (ec)
82     {
83         lg2::error("Disable usb code update failed");
84         return;
85     }
86     lg2::info("Disable usb code update");
87 }
88 
saveUSBCodeUpdateStateToFile(const bool & maskedState,const bool & enabledState)89 void ServiceConfig::saveUSBCodeUpdateStateToFile(const bool& maskedState,
90                                                  const bool& enabledState)
91 {
92     if (!std::filesystem::exists(usbCodeUpdateStateFilePath))
93     {
94         std::filesystem::create_directories(usbCodeUpdateStateFilePath);
95     }
96 
97     UsbCodeUpdateStateMap usbCodeUpdateState;
98     usbCodeUpdateState[srvCfgPropMasked] = maskedState;
99     usbCodeUpdateState[srvCfgPropEnabled] = enabledState;
100 
101     std::ofstream file(usbCodeUpdateStateFile, std::ios::out);
102     cereal::JSONOutputArchive archive(file);
103     archive(CEREAL_NVP(usbCodeUpdateState));
104 }
105 
getUSBCodeUpdateStateFromFile()106 void ServiceConfig::getUSBCodeUpdateStateFromFile()
107 {
108     if (!std::filesystem::exists(usbCodeUpdateStateFile))
109     {
110         lg2::info("usb-code-update-state file does not exist");
111 
112         unitMaskedState = false;
113         unitEnabledState = true;
114         unitRunningState = true;
115         setUSBCodeUpdateState(unitEnabledState);
116         return;
117     }
118 
119     std::ifstream file(usbCodeUpdateStateFile);
120     cereal::JSONInputArchive archive(file);
121     UsbCodeUpdateStateMap usbCodeUpdateState;
122     archive(usbCodeUpdateState);
123 
124     auto iterMask = usbCodeUpdateState.find(srvCfgPropMasked);
125     if (iterMask != usbCodeUpdateState.end())
126     {
127         unitMaskedState = iterMask->second;
128         if (unitMaskedState)
129         {
130             unitEnabledState = !unitMaskedState;
131             unitRunningState = !unitMaskedState;
132             setUSBCodeUpdateState(unitEnabledState);
133             return;
134         }
135 
136         auto iterEnable = usbCodeUpdateState.find(srvCfgPropEnabled);
137         if (iterEnable != usbCodeUpdateState.end())
138         {
139             unitEnabledState = iterEnable->second;
140             unitRunningState = iterEnable->second;
141             setUSBCodeUpdateState(unitEnabledState);
142         }
143     }
144 }
145 #endif
146 
updateSocketProperties(const boost::container::flat_map<std::string,VariantType> & propertyMap)147 void ServiceConfig::updateSocketProperties(
148     const boost::container::flat_map<std::string, VariantType>& propertyMap)
149 {
150     auto listenIt = propertyMap.find("Listen");
151     if (listenIt != propertyMap.end())
152     {
153         auto listenVal =
154             std::get<std::vector<std::tuple<std::string, std::string>>>(
155                 listenIt->second);
156         if (listenVal.size())
157         {
158             protocol = std::get<0>(listenVal[0]);
159             std::string port = std::get<1>(listenVal[0]);
160             auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
161                                   nullptr, 10);
162             if (tmp > std::numeric_limits<uint16_t>::max())
163             {
164                 throw std::out_of_range("Out of range");
165             }
166             portNum = tmp;
167             if (sockAttrIface && sockAttrIface->is_initialized())
168             {
169                 internalSet = true;
170                 sockAttrIface->set_property(sockAttrPropPort, portNum);
171                 internalSet = false;
172             }
173         }
174     }
175 }
176 
updateServiceProperties(const boost::container::flat_map<std::string,VariantType> & propertyMap)177 void ServiceConfig::updateServiceProperties(
178     const boost::container::flat_map<std::string, VariantType>& propertyMap)
179 {
180     auto stateIt = propertyMap.find("UnitFileState");
181     if (stateIt != propertyMap.end())
182     {
183         stateValue = std::get<std::string>(stateIt->second);
184         unitEnabledState = unitMaskedState = false;
185         if (stateValue == stateMasked)
186         {
187             unitMaskedState = true;
188         }
189         else if (stateValue == stateEnabled)
190         {
191             unitEnabledState = true;
192         }
193         if (srvCfgIface && srvCfgIface->is_initialized())
194         {
195             internalSet = true;
196             srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
197             srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
198             internalSet = false;
199         }
200     }
201     auto subStateIt = propertyMap.find("SubState");
202     if (subStateIt != propertyMap.end())
203     {
204         subStateValue = std::get<std::string>(subStateIt->second);
205         if (subStateValue == subStateRunning ||
206             subStateValue == subStateListening)
207         {
208             unitRunningState = true;
209         }
210         if (srvCfgIface && srvCfgIface->is_initialized())
211         {
212             internalSet = true;
213             srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
214             internalSet = false;
215         }
216     }
217 
218 #ifdef USB_CODE_UPDATE
219     if (baseUnitName == usbCodeUpdateUnitName)
220     {
221         getUSBCodeUpdateStateFromFile();
222     }
223 #endif
224 }
225 
queryAndUpdateProperties()226 void ServiceConfig::queryAndUpdateProperties()
227 {
228     std::string objectPath =
229         isSocketActivatedService ? socketObjectPath : serviceObjectPath;
230     if (objectPath.empty())
231     {
232         return;
233     }
234 
235     conn->async_method_call(
236         [this](boost::system::error_code ec,
237                const boost::container::flat_map<std::string, VariantType>&
238                    propertyMap) {
239             if (ec)
240             {
241                 lg2::error(
242                     "async_method_call error: Failed to service unit properties: {EC}",
243                     "EC", ec.value());
244                 return;
245             }
246             try
247             {
248                 updateServiceProperties(propertyMap);
249                 if (!socketObjectPath.empty())
250                 {
251                     conn->async_method_call(
252                         [this](boost::system::error_code ec,
253                                const boost::container::flat_map<
254                                    std::string, VariantType>& propertyMap) {
255                             if (ec)
256                             {
257                                 lg2::error(
258                                     "async_method_call error: Failed to get all property: {EC}",
259                                     "EC", ec.value());
260                                 return;
261                             }
262                             try
263                             {
264                                 updateSocketProperties(propertyMap);
265                                 if (!srvCfgIface)
266                                 {
267                                     registerProperties();
268                                 }
269                             }
270                             catch (const std::exception& e)
271                             {
272                                 lg2::error(
273                                     "Exception in getting socket properties: {ERROR}",
274                                     "ERROR", e);
275                                 return;
276                             }
277                         },
278                         sysdService, socketObjectPath, dBusPropIntf,
279                         dBusGetAllMethod, sysdSocketIntf);
280                 }
281                 else if (!srvCfgIface)
282                 {
283                     registerProperties();
284                 }
285             }
286             catch (const std::exception& e)
287             {
288                 lg2::error("Exception in getting socket properties: {ERROR}",
289                            "ERROR", e);
290                 return;
291             }
292         },
293         sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
294     return;
295 }
296 
createSocketOverrideConf()297 void ServiceConfig::createSocketOverrideConf()
298 {
299     if (!socketObjectPath.empty())
300     {
301         std::string socketUnitName(instantiatedUnitName + ".socket");
302         /// Check override socket directory exist, if not create it.
303         std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
304         ovrUnitFileDir += socketUnitName;
305         ovrUnitFileDir += ".d";
306         if (!std::filesystem::exists(ovrUnitFileDir))
307         {
308             if (!std::filesystem::create_directories(ovrUnitFileDir))
309             {
310                 lg2::error("Unable to create the {DIR} directory.", "DIR",
311                            ovrUnitFileDir);
312                 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
313                                             Common::Error::InternalFailure>();
314             }
315         }
316         overrideConfDir = std::string(ovrUnitFileDir);
317     }
318 }
319 
ServiceConfig(sdbusplus::asio::object_server & srv_,std::shared_ptr<sdbusplus::asio::connection> & conn_,const std::string & objPath_,const std::string & baseUnitName_,const std::string & instanceName_,const std::string & serviceObjPath_,const std::string & socketObjPath_)320 ServiceConfig::ServiceConfig(
321     sdbusplus::asio::object_server& srv_,
322     std::shared_ptr<sdbusplus::asio::connection>& conn_,
323     const std::string& objPath_, const std::string& baseUnitName_,
324     const std::string& instanceName_, const std::string& serviceObjPath_,
325     const std::string& socketObjPath_) :
326     conn(conn_), server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
327     instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
328     socketObjectPath(socketObjPath_)
329 {
330     isSocketActivatedService = serviceObjectPath.empty();
331     instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
332     updatedFlag = 0;
333     queryAndUpdateProperties();
334     return;
335 }
336 
getSocketUnitName()337 std::string ServiceConfig::getSocketUnitName()
338 {
339     return instantiatedUnitName + ".socket";
340 }
341 
getServiceUnitName()342 std::string ServiceConfig::getServiceUnitName()
343 {
344     return instantiatedUnitName + ".service";
345 }
346 
isMaskedOut()347 bool ServiceConfig::isMaskedOut()
348 {
349     // return true  if state is masked & no request to update the maskedState
350     return (
351         stateValue == "masked" &&
352         !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
353 }
354 
stopAndApplyUnitConfig(boost::asio::yield_context yield)355 void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
356 {
357     if (!updatedFlag || isMaskedOut())
358     {
359         // No updates / masked - Just return.
360         return;
361     }
362     lg2::info("Applying new settings: {OBJPATH}", "OBJPATH", objPath);
363     if (subStateValue == subStateRunning || subStateValue == subStateListening)
364     {
365         if (!socketObjectPath.empty())
366         {
367             systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
368         }
369         if (!isSocketActivatedService)
370         {
371             systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
372         }
373         else
374         {
375             // For socket-activated service, each connection will spawn a
376             // service instance from template. Need to find all spawned service
377             // `<unitName>@<attribute>.service` and stop them through the
378             // systemdUnitAction method
379             boost::system::error_code ec;
380             auto listUnits =
381                 conn->yield_method_call<std::vector<ListUnitsType>>(
382                     yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
383                     "ListUnits");
384 
385             checkAndThrowInternalFailure(
386                 ec, "yield_method_call error: ListUnits failed");
387 
388             for (const auto& unit : listUnits)
389             {
390                 const auto& service =
391                     std::get<static_cast<int>(ListUnitElements::name)>(unit);
392                 const auto& status =
393                     std::get<static_cast<int>(ListUnitElements::subState)>(
394                         unit);
395                 if (service.find(baseUnitName + "@") != std::string::npos &&
396                     service.find(".service") != std::string::npos &&
397                     status == subStateRunning)
398                 {
399                     systemdUnitAction(conn, yield, service, sysdStopUnit);
400                 }
401             }
402         }
403     }
404 
405     if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
406     {
407         createSocketOverrideConf();
408         // Create override config file and write data.
409         std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
410         std::string tmpFile{ovrCfgFile + "_tmp"};
411         std::ofstream cfgFile(tmpFile, std::ios::out);
412         if (!cfgFile.good())
413         {
414             lg2::error("Failed to open the {TMPFILE} file.", "TMPFILE",
415                        tmpFile);
416             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
417                                         Error::InternalFailure>();
418         }
419 
420         // Write the socket header
421         cfgFile << "[Socket]\n";
422         // Listen
423         cfgFile << "Listen" << protocol << "="
424                 << "\n";
425         cfgFile << "Listen" << protocol << "=" << portNum << "\n";
426         cfgFile.close();
427 
428         if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
429         {
430             lg2::error("Failed to rename {TMPFILE} file as {OVERCFGFILE} file.",
431                        "TMPFILE", tmpFile, "OVERCFGFILE", ovrCfgFile);
432             std::remove(tmpFile.c_str());
433             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
434                                         Error::InternalFailure>();
435         }
436     }
437 
438     if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
439                        (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
440     {
441         std::vector<std::string> unitFiles;
442         if (socketObjectPath.empty())
443         {
444             unitFiles = {getServiceUnitName()};
445         }
446         else if (serviceObjectPath.empty())
447         {
448             unitFiles = {getSocketUnitName()};
449         }
450         else
451         {
452             unitFiles = {getSocketUnitName(), getServiceUnitName()};
453         }
454         systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
455                                     unitMaskedState, unitEnabledState);
456     }
457     return;
458 }
restartUnitConfig(boost::asio::yield_context yield)459 void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
460 {
461     if (!updatedFlag || isMaskedOut())
462     {
463         // No updates. Just return.
464         return;
465     }
466 
467     if (unitRunningState)
468     {
469         if (!socketObjectPath.empty())
470         {
471             systemdUnitAction(conn, yield, getSocketUnitName(),
472                               sysdRestartUnit);
473         }
474         if (!serviceObjectPath.empty())
475         {
476             systemdUnitAction(conn, yield, getServiceUnitName(),
477                               sysdRestartUnit);
478         }
479     }
480 
481     // Reset the flag
482     updatedFlag = 0;
483 
484     lg2::info("Applied new settings: {OBJPATH}", "OBJPATH", objPath);
485 
486     queryAndUpdateProperties();
487     return;
488 }
489 
startServiceRestartTimer()490 void ServiceConfig::startServiceRestartTimer()
491 {
492     timer->expires_after(std::chrono::seconds(restartTimeout));
493     timer->async_wait([this](const boost::system::error_code& ec) {
494         if (ec == boost::asio::error::operation_aborted)
495         {
496             // Timer reset.
497             return;
498         }
499         else if (ec)
500         {
501             lg2::error("async wait error: {EC}", "EC", ec.value());
502             return;
503         }
504         updateInProgress = true;
505         boost::asio::spawn(
506             conn->get_io_context(),
507             [this](boost::asio::yield_context yield) {
508                 // Stop and apply configuration for all objects
509                 for (auto& srvMgrObj : srvMgrObjects)
510                 {
511                     auto& srvObj = srvMgrObj.second;
512                     if (srvObj->updatedFlag)
513                     {
514                         srvObj->stopAndApplyUnitConfig(yield);
515                     }
516                 }
517                 // Do system reload
518                 systemdDaemonReload(conn, yield);
519                 // restart unit config.
520                 for (auto& srvMgrObj : srvMgrObjects)
521                 {
522                     auto& srvObj = srvMgrObj.second;
523                     if (srvObj->updatedFlag)
524                     {
525                         srvObj->restartUnitConfig(yield);
526                     }
527                 }
528                 updateInProgress = false;
529             },
530             boost::asio::detached);
531     });
532 }
533 
registerProperties()534 void ServiceConfig::registerProperties()
535 {
536     srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
537 
538     if (!socketObjectPath.empty())
539     {
540         sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
541         sockAttrIface->register_property(
542             sockAttrPropPort, portNum,
543             [this](const uint16_t& req, uint16_t& res) {
544                 if (!internalSet)
545                 {
546                     if (req == res)
547                     {
548                         return 1;
549                     }
550                     if (updateInProgress)
551                     {
552                         return 0;
553                     }
554                     portNum = req;
555                     updatedFlag |=
556                         (1 << static_cast<uint8_t>(UpdatedProp::port));
557                     startServiceRestartTimer();
558                 }
559                 res = req;
560                 return 1;
561             });
562     }
563 
564     srvCfgIface->register_property(
565         srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
566             if (!internalSet)
567             {
568 #ifdef USB_CODE_UPDATE
569                 if (baseUnitName == usbCodeUpdateUnitName)
570                 {
571                     unitMaskedState = req;
572                     unitEnabledState = !unitMaskedState;
573                     unitRunningState = !unitMaskedState;
574                     internalSet = true;
575                     srvCfgIface->set_property(srvCfgPropEnabled,
576                                               unitEnabledState);
577                     srvCfgIface->set_property(srvCfgPropRunning,
578                                               unitRunningState);
579                     srvCfgIface->set_property(srvCfgPropMasked,
580                                               unitMaskedState);
581                     internalSet = false;
582                     setUSBCodeUpdateState(unitEnabledState);
583                     saveUSBCodeUpdateStateToFile(unitMaskedState,
584                                                  unitEnabledState);
585                     return 1;
586                 }
587 #endif
588                 if (req == res)
589                 {
590                     return 1;
591                 }
592                 if (updateInProgress)
593                 {
594                     return 0;
595                 }
596                 unitMaskedState = req;
597                 unitEnabledState = !unitMaskedState;
598                 unitRunningState = !unitMaskedState;
599                 updatedFlag |=
600                     (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
601                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
602                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
603                 internalSet = true;
604                 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
605                 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
606                 internalSet = false;
607                 startServiceRestartTimer();
608             }
609             res = req;
610             return 1;
611         });
612 
613     srvCfgIface->register_property(
614         srvCfgPropEnabled, unitEnabledState,
615         [this](const bool& req, bool& res) {
616             if (!internalSet)
617             {
618 #ifdef USB_CODE_UPDATE
619                 if (baseUnitName == usbCodeUpdateUnitName)
620                 {
621                     if (unitMaskedState)
622                     { // block updating if masked
623                         lg2::error("Invalid value specified");
624                         return -EINVAL;
625                     }
626                     unitEnabledState = req;
627                     unitRunningState = req;
628                     internalSet = true;
629                     srvCfgIface->set_property(srvCfgPropEnabled,
630                                               unitEnabledState);
631                     srvCfgIface->set_property(srvCfgPropRunning,
632                                               unitRunningState);
633                     internalSet = false;
634                     setUSBCodeUpdateState(unitEnabledState);
635                     saveUSBCodeUpdateStateToFile(unitMaskedState,
636                                                  unitEnabledState);
637                     res = req;
638                     return 1;
639                 }
640 #endif
641                 if (req == res)
642                 {
643                     return 1;
644                 }
645                 if (updateInProgress)
646                 {
647                     return 0;
648                 }
649                 if (unitMaskedState)
650                 { // block updating if masked
651                     lg2::error("Invalid value specified");
652                     return -EINVAL;
653                 }
654                 unitEnabledState = req;
655                 updatedFlag |=
656                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
657                 startServiceRestartTimer();
658             }
659             res = req;
660             return 1;
661         });
662 
663     srvCfgIface->register_property(
664         srvCfgPropRunning, unitRunningState,
665         [this](const bool& req, bool& res) {
666             if (!internalSet)
667             {
668 #ifdef USB_CODE_UPDATE
669                 if (baseUnitName == usbCodeUpdateUnitName)
670                 {
671                     if (unitMaskedState)
672                     { // block updating if masked
673                         lg2::error("Invalid value specified");
674                         return -EINVAL;
675                     }
676                     unitEnabledState = req;
677                     unitRunningState = req;
678                     internalSet = true;
679                     srvCfgIface->set_property(srvCfgPropEnabled,
680                                               unitEnabledState);
681                     srvCfgIface->set_property(srvCfgPropRunning,
682                                               unitRunningState);
683                     internalSet = false;
684                     setUSBCodeUpdateState(unitEnabledState);
685                     saveUSBCodeUpdateStateToFile(unitMaskedState,
686                                                  unitEnabledState);
687                     res = req;
688                     return 1;
689                 }
690 #endif
691                 if (req == res)
692                 {
693                     return 1;
694                 }
695                 if (updateInProgress)
696                 {
697                     return 0;
698                 }
699                 if (unitMaskedState)
700                 { // block updating if masked
701                     lg2::error("Invalid value specified");
702                     return -EINVAL;
703                 }
704                 unitRunningState = req;
705                 updatedFlag |=
706                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
707                 startServiceRestartTimer();
708             }
709             res = req;
710             return 1;
711         });
712 
713     srvCfgIface->initialize();
714     if (!socketObjectPath.empty())
715     {
716         sockAttrIface->initialize();
717     }
718     return;
719 }
720 
721 } // namespace service
722 } // namespace phosphor
723