xref: /openbmc/service-config-manager/src/srvcfg_manager.cpp (revision ee853eb2d865c7da9eec99cdcac04f8aee750e49)
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 */
16*ee853eb2SAppaRao Puli #include "srvcfg_manager.hpp"
17*ee853eb2SAppaRao Puli 
18*ee853eb2SAppaRao Puli #include <boost/asio/spawn.hpp>
19*ee853eb2SAppaRao Puli 
200084047dSAppaRao Puli #include <fstream>
210084047dSAppaRao Puli #include <regex>
220084047dSAppaRao Puli 
2333816cf9SRichard Marian Thomaiyar extern std::unique_ptr<boost::asio::steady_timer> timer;
240084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
250084047dSAppaRao Puli     srvMgrObjects;
2690f2da3fSRichard Marian Thomaiyar static bool updateInProgress = false;
270084047dSAppaRao Puli 
280084047dSAppaRao Puli namespace phosphor
290084047dSAppaRao Puli {
300084047dSAppaRao Puli namespace service
310084047dSAppaRao Puli {
320084047dSAppaRao Puli 
330084047dSAppaRao Puli static constexpr const char* overrideConfFileName = "override.conf";
340084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds
350084047dSAppaRao Puli 
360084047dSAppaRao Puli static constexpr const char* systemd1UnitBasePath =
370084047dSAppaRao Puli     "/org/freedesktop/systemd1/unit/";
380084047dSAppaRao Puli static constexpr const char* systemdOverrideUnitBasePath =
390084047dSAppaRao Puli     "/etc/systemd/system/";
400084047dSAppaRao Puli 
4190f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateSocketProperties(
4290f2da3fSRichard Marian Thomaiyar     const boost::container::flat_map<std::string, VariantType>& propertyMap)
430084047dSAppaRao Puli {
4490f2da3fSRichard Marian Thomaiyar     auto listenIt = propertyMap.find("Listen");
4590f2da3fSRichard Marian Thomaiyar     if (listenIt != propertyMap.end())
460084047dSAppaRao Puli     {
4790f2da3fSRichard Marian Thomaiyar         auto listenVal =
4890f2da3fSRichard Marian Thomaiyar             std::get<std::vector<std::tuple<std::string, std::string>>>(
4990f2da3fSRichard Marian Thomaiyar                 listenIt->second);
5090f2da3fSRichard Marian Thomaiyar         if (listenVal.size())
510084047dSAppaRao Puli         {
520084047dSAppaRao Puli             protocol = std::get<0>(listenVal[0]);
530084047dSAppaRao Puli             std::string port = std::get<1>(listenVal[0]);
540084047dSAppaRao Puli             auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
550084047dSAppaRao Puli                                   nullptr, 10);
560084047dSAppaRao Puli             if (tmp > std::numeric_limits<uint16_t>::max())
570084047dSAppaRao Puli             {
580084047dSAppaRao Puli                 throw std::out_of_range("Out of range");
590084047dSAppaRao Puli             }
600084047dSAppaRao Puli             portNum = tmp;
6190f2da3fSRichard Marian Thomaiyar             if (iface && iface->is_initialized())
6290f2da3fSRichard Marian Thomaiyar             {
6390f2da3fSRichard Marian Thomaiyar                 internalSet = true;
6490f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropPort, portNum);
6590f2da3fSRichard Marian Thomaiyar                 internalSet = false;
6690f2da3fSRichard Marian Thomaiyar             }
6790f2da3fSRichard Marian Thomaiyar         }
6890f2da3fSRichard Marian Thomaiyar     }
6990f2da3fSRichard Marian Thomaiyar }
7090f2da3fSRichard Marian Thomaiyar 
7190f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateServiceProperties(
7290f2da3fSRichard Marian Thomaiyar     const boost::container::flat_map<std::string, VariantType>& propertyMap)
7390f2da3fSRichard Marian Thomaiyar {
7490f2da3fSRichard Marian Thomaiyar     auto stateIt = propertyMap.find("UnitFileState");
7590f2da3fSRichard Marian Thomaiyar     if (stateIt != propertyMap.end())
7690f2da3fSRichard Marian Thomaiyar     {
7790f2da3fSRichard Marian Thomaiyar         stateValue = std::get<std::string>(stateIt->second);
7890f2da3fSRichard Marian Thomaiyar         unitEnabledState = unitMaskedState = false;
7990f2da3fSRichard Marian Thomaiyar         if (stateValue == stateMasked)
8090f2da3fSRichard Marian Thomaiyar         {
8190f2da3fSRichard Marian Thomaiyar             unitMaskedState = true;
8290f2da3fSRichard Marian Thomaiyar         }
8390f2da3fSRichard Marian Thomaiyar         else if (stateValue == stateEnabled)
8490f2da3fSRichard Marian Thomaiyar         {
8590f2da3fSRichard Marian Thomaiyar             unitEnabledState = true;
8690f2da3fSRichard Marian Thomaiyar         }
8790f2da3fSRichard Marian Thomaiyar         if (iface && iface->is_initialized())
8890f2da3fSRichard Marian Thomaiyar         {
8990f2da3fSRichard Marian Thomaiyar             internalSet = true;
9090f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropMasked, unitMaskedState);
9190f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropEnabled, unitEnabledState);
9290f2da3fSRichard Marian Thomaiyar             internalSet = false;
9390f2da3fSRichard Marian Thomaiyar         }
9490f2da3fSRichard Marian Thomaiyar     }
9590f2da3fSRichard Marian Thomaiyar     auto subStateIt = propertyMap.find("SubState");
9690f2da3fSRichard Marian Thomaiyar     if (subStateIt != propertyMap.end())
9790f2da3fSRichard Marian Thomaiyar     {
9890f2da3fSRichard Marian Thomaiyar         subStateValue = std::get<std::string>(subStateIt->second);
9990f2da3fSRichard Marian Thomaiyar         if (subStateValue == subStateRunning)
10090f2da3fSRichard Marian Thomaiyar         {
10190f2da3fSRichard Marian Thomaiyar             unitRunningState = true;
10290f2da3fSRichard Marian Thomaiyar         }
10390f2da3fSRichard Marian Thomaiyar         if (iface && iface->is_initialized())
10490f2da3fSRichard Marian Thomaiyar         {
10590f2da3fSRichard Marian Thomaiyar             internalSet = true;
10690f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropRunning, unitRunningState);
10790f2da3fSRichard Marian Thomaiyar             internalSet = false;
10890f2da3fSRichard Marian Thomaiyar         }
10990f2da3fSRichard Marian Thomaiyar     }
11090f2da3fSRichard Marian Thomaiyar }
11190f2da3fSRichard Marian Thomaiyar 
11290f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties()
11390f2da3fSRichard Marian Thomaiyar {
11490f2da3fSRichard Marian Thomaiyar     conn->async_method_call(
11590f2da3fSRichard Marian Thomaiyar         [this](boost::system::error_code ec,
116*ee853eb2SAppaRao Puli                const boost::container::flat_map<std::string, VariantType>&
117*ee853eb2SAppaRao Puli                    propertyMap) {
11890f2da3fSRichard Marian Thomaiyar             if (ec)
11990f2da3fSRichard Marian Thomaiyar             {
12090f2da3fSRichard Marian Thomaiyar                 phosphor::logging::log<phosphor::logging::level::ERR>(
12190f2da3fSRichard Marian Thomaiyar                     "async_method_call error: Failed to service unit "
12290f2da3fSRichard Marian Thomaiyar                     "properties");
12390f2da3fSRichard Marian Thomaiyar                 return;
12490f2da3fSRichard Marian Thomaiyar             }
12590f2da3fSRichard Marian Thomaiyar             try
12690f2da3fSRichard Marian Thomaiyar             {
12790f2da3fSRichard Marian Thomaiyar                 updateServiceProperties(propertyMap);
12890f2da3fSRichard Marian Thomaiyar                 if (!socketObjectPath.empty())
12990f2da3fSRichard Marian Thomaiyar                 {
13090f2da3fSRichard Marian Thomaiyar                     conn->async_method_call(
13190f2da3fSRichard Marian Thomaiyar                         [this](boost::system::error_code ec,
13290f2da3fSRichard Marian Thomaiyar                                const boost::container::flat_map<
13390f2da3fSRichard Marian Thomaiyar                                    std::string, VariantType>& propertyMap) {
13490f2da3fSRichard Marian Thomaiyar                             if (ec)
13590f2da3fSRichard Marian Thomaiyar                             {
13690f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
13790f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
13890f2da3fSRichard Marian Thomaiyar                                     "async_method_call error: Failed to get "
13990f2da3fSRichard Marian Thomaiyar                                     "all property");
14090f2da3fSRichard Marian Thomaiyar                                 return;
14190f2da3fSRichard Marian Thomaiyar                             }
14290f2da3fSRichard Marian Thomaiyar                             try
14390f2da3fSRichard Marian Thomaiyar                             {
14490f2da3fSRichard Marian Thomaiyar                                 updateSocketProperties(propertyMap);
14590f2da3fSRichard Marian Thomaiyar                                 if (!iface)
14690f2da3fSRichard Marian Thomaiyar                                 {
14790f2da3fSRichard Marian Thomaiyar                                     registerProperties();
14890f2da3fSRichard Marian Thomaiyar                                 }
14990f2da3fSRichard Marian Thomaiyar                             }
15090f2da3fSRichard Marian Thomaiyar                             catch (const std::exception& e)
15190f2da3fSRichard Marian Thomaiyar                             {
15290f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
15390f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
15490f2da3fSRichard Marian Thomaiyar                                     "Exception in getting socket properties",
15590f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::entry("WHAT=%s",
15690f2da3fSRichard Marian Thomaiyar                                                              e.what()));
15790f2da3fSRichard Marian Thomaiyar                                 return;
15890f2da3fSRichard Marian Thomaiyar                             }
15990f2da3fSRichard Marian Thomaiyar                         },
16090f2da3fSRichard Marian Thomaiyar                         sysdService, socketObjectPath, dBusPropIntf,
16190f2da3fSRichard Marian Thomaiyar                         dBusGetAllMethod, sysdSocketIntf);
16290f2da3fSRichard Marian Thomaiyar                 }
16390f2da3fSRichard Marian Thomaiyar                 else if (!iface)
16490f2da3fSRichard Marian Thomaiyar                 {
16590f2da3fSRichard Marian Thomaiyar                     registerProperties();
16690f2da3fSRichard Marian Thomaiyar                 }
1670084047dSAppaRao Puli             }
1680084047dSAppaRao Puli             catch (const std::exception& e)
1690084047dSAppaRao Puli             {
1700084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
17190f2da3fSRichard Marian Thomaiyar                     "Exception in getting socket properties",
1720084047dSAppaRao Puli                     phosphor::logging::entry("WHAT=%s", e.what()));
1730084047dSAppaRao Puli                 return;
1740084047dSAppaRao Puli             }
1750084047dSAppaRao Puli         },
17690f2da3fSRichard Marian Thomaiyar         sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod,
17790f2da3fSRichard Marian Thomaiyar         sysdUnitIntf);
1780084047dSAppaRao Puli     return;
1790084047dSAppaRao Puli }
1800084047dSAppaRao Puli 
18190f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf()
1820084047dSAppaRao Puli {
18390f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
1840084047dSAppaRao Puli     {
18590f2da3fSRichard Marian Thomaiyar         std::string socketUnitName(instantiatedUnitName + ".socket");
1860084047dSAppaRao Puli         /// Check override socket directory exist, if not create it.
1870084047dSAppaRao Puli         std::experimental::filesystem::path ovrUnitFileDir(
1880084047dSAppaRao Puli             systemdOverrideUnitBasePath);
1890084047dSAppaRao Puli         ovrUnitFileDir += socketUnitName;
1900084047dSAppaRao Puli         ovrUnitFileDir += ".d";
1910084047dSAppaRao Puli         if (!std::experimental::filesystem::exists(ovrUnitFileDir))
1920084047dSAppaRao Puli         {
19390f2da3fSRichard Marian Thomaiyar             if (!std::experimental::filesystem::create_directories(
19490f2da3fSRichard Marian Thomaiyar                     ovrUnitFileDir))
1950084047dSAppaRao Puli             {
1960084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
1970084047dSAppaRao Puli                     "Unable to create the directory.",
1980084047dSAppaRao Puli                     phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
19990f2da3fSRichard Marian Thomaiyar                 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
20090f2da3fSRichard Marian Thomaiyar                                             Common::Error::InternalFailure>();
20190f2da3fSRichard Marian Thomaiyar             }
20290f2da3fSRichard Marian Thomaiyar         }
20390f2da3fSRichard Marian Thomaiyar         overrideConfDir = std::string(ovrUnitFileDir);
2040084047dSAppaRao Puli     }
2050084047dSAppaRao Puli }
2060084047dSAppaRao Puli 
20790f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig(
20890f2da3fSRichard Marian Thomaiyar     sdbusplus::asio::object_server& srv_,
20990f2da3fSRichard Marian Thomaiyar     std::shared_ptr<sdbusplus::asio::connection>& conn_,
21090f2da3fSRichard Marian Thomaiyar     const std::string& objPath_, const std::string& baseUnitName_,
21190f2da3fSRichard Marian Thomaiyar     const std::string& instanceName_, const std::string& serviceObjPath_,
21290f2da3fSRichard Marian Thomaiyar     const std::string& socketObjPath_) :
21390f2da3fSRichard Marian Thomaiyar     server(srv_),
21490f2da3fSRichard Marian Thomaiyar     conn(conn_), objPath(objPath_), baseUnitName(baseUnitName_),
21590f2da3fSRichard Marian Thomaiyar     instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
21690f2da3fSRichard Marian Thomaiyar     socketObjectPath(socketObjPath_)
21790f2da3fSRichard Marian Thomaiyar {
21890f2da3fSRichard Marian Thomaiyar     instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
2190084047dSAppaRao Puli     updatedFlag = 0;
22090f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
2210084047dSAppaRao Puli     return;
2220084047dSAppaRao Puli }
2230084047dSAppaRao Puli 
22490f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName()
2250084047dSAppaRao Puli {
22690f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".socket";
227e55cfd6eSAppaRao Puli }
228e55cfd6eSAppaRao Puli 
22990f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName()
23090f2da3fSRichard Marian Thomaiyar {
23190f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".service";
23290f2da3fSRichard Marian Thomaiyar }
23390f2da3fSRichard Marian Thomaiyar 
23490f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut()
23590f2da3fSRichard Marian Thomaiyar {
23690f2da3fSRichard Marian Thomaiyar     // return true  if state is masked & no request to update the maskedState
23790f2da3fSRichard Marian Thomaiyar     return (
23890f2da3fSRichard Marian Thomaiyar         stateValue == "masked" &&
23990f2da3fSRichard Marian Thomaiyar         !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
24090f2da3fSRichard Marian Thomaiyar }
24190f2da3fSRichard Marian Thomaiyar 
24290f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
24390f2da3fSRichard Marian Thomaiyar {
24490f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
24590f2da3fSRichard Marian Thomaiyar     {
24690f2da3fSRichard Marian Thomaiyar         // No updates / masked - Just return.
24790f2da3fSRichard Marian Thomaiyar         return;
24890f2da3fSRichard Marian Thomaiyar     }
2490084047dSAppaRao Puli     phosphor::logging::log<phosphor::logging::level::INFO>(
2500084047dSAppaRao Puli         "Applying new settings.",
2510084047dSAppaRao Puli         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
25290f2da3fSRichard Marian Thomaiyar     if (subStateValue == "running")
2530084047dSAppaRao Puli     {
25490f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
25590f2da3fSRichard Marian Thomaiyar         {
25690f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
25790f2da3fSRichard Marian Thomaiyar         }
25890f2da3fSRichard Marian Thomaiyar         systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
25990f2da3fSRichard Marian Thomaiyar     }
26090f2da3fSRichard Marian Thomaiyar 
26190f2da3fSRichard Marian Thomaiyar     if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
26290f2da3fSRichard Marian Thomaiyar     {
26390f2da3fSRichard Marian Thomaiyar         createSocketOverrideConf();
2640084047dSAppaRao Puli         // Create override config file and write data.
26590f2da3fSRichard Marian Thomaiyar         std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
2660084047dSAppaRao Puli         std::string tmpFile{ovrCfgFile + "_tmp"};
2670084047dSAppaRao Puli         std::ofstream cfgFile(tmpFile, std::ios::out);
2680084047dSAppaRao Puli         if (!cfgFile.good())
2690084047dSAppaRao Puli         {
2700084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
2710084047dSAppaRao Puli                 "Failed to open override.conf_tmp file");
2720084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
2730084047dSAppaRao Puli                                         Error::InternalFailure>();
2740084047dSAppaRao Puli         }
2750084047dSAppaRao Puli 
2760084047dSAppaRao Puli         // Write the socket header
2770084047dSAppaRao Puli         cfgFile << "[Socket]\n";
2780084047dSAppaRao Puli         // Listen
2790084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "="
2800084047dSAppaRao Puli                 << "\n";
2810084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "=" << portNum << "\n";
2820084047dSAppaRao Puli         cfgFile.close();
2830084047dSAppaRao Puli 
2840084047dSAppaRao Puli         if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
2850084047dSAppaRao Puli         {
2860084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
2870084047dSAppaRao Puli                 "Failed to rename tmp file as override.conf");
2880084047dSAppaRao Puli             std::remove(tmpFile.c_str());
2890084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
2900084047dSAppaRao Puli                                         Error::InternalFailure>();
2910084047dSAppaRao Puli         }
292e55cfd6eSAppaRao Puli     }
2930084047dSAppaRao Puli 
29490f2da3fSRichard Marian Thomaiyar     if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
29590f2da3fSRichard Marian Thomaiyar                        (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
296e55cfd6eSAppaRao Puli     {
29790f2da3fSRichard Marian Thomaiyar         std::vector<std::string> unitFiles;
29890f2da3fSRichard Marian Thomaiyar         if (socketObjectPath.empty())
29990f2da3fSRichard Marian Thomaiyar         {
30090f2da3fSRichard Marian Thomaiyar             unitFiles = {getServiceUnitName()};
301e55cfd6eSAppaRao Puli         }
30290f2da3fSRichard Marian Thomaiyar         else
303e55cfd6eSAppaRao Puli         {
30490f2da3fSRichard Marian Thomaiyar             unitFiles = {getSocketUnitName(), getServiceUnitName()};
30590f2da3fSRichard Marian Thomaiyar         }
30690f2da3fSRichard Marian Thomaiyar         systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
30790f2da3fSRichard Marian Thomaiyar                                     unitMaskedState, unitEnabledState);
30890f2da3fSRichard Marian Thomaiyar     }
30990f2da3fSRichard Marian Thomaiyar     return;
31090f2da3fSRichard Marian Thomaiyar }
31190f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
31290f2da3fSRichard Marian Thomaiyar {
31390f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
31490f2da3fSRichard Marian Thomaiyar     {
31590f2da3fSRichard Marian Thomaiyar         // No updates. Just return.
31690f2da3fSRichard Marian Thomaiyar         return;
3170084047dSAppaRao Puli     }
3180084047dSAppaRao Puli 
31990f2da3fSRichard Marian Thomaiyar     if (unitRunningState)
3200084047dSAppaRao Puli     {
32190f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
32290f2da3fSRichard Marian Thomaiyar         {
32390f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(),
32490f2da3fSRichard Marian Thomaiyar                               sysdRestartUnit);
3250084047dSAppaRao Puli         }
32690f2da3fSRichard Marian Thomaiyar         systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit);
3270084047dSAppaRao Puli     }
3280084047dSAppaRao Puli 
3290084047dSAppaRao Puli     // Reset the flag
3300084047dSAppaRao Puli     updatedFlag = 0;
3310084047dSAppaRao Puli 
33290f2da3fSRichard Marian Thomaiyar     phosphor::logging::log<phosphor::logging::level::INFO>(
33390f2da3fSRichard Marian Thomaiyar         "Applied new settings",
33490f2da3fSRichard Marian Thomaiyar         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
3350084047dSAppaRao Puli 
33690f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
3370084047dSAppaRao Puli     return;
3380084047dSAppaRao Puli }
3390084047dSAppaRao Puli 
3400084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer()
3410084047dSAppaRao Puli {
34233816cf9SRichard Marian Thomaiyar     timer->expires_after(std::chrono::seconds(restartTimeout));
3430084047dSAppaRao Puli     timer->async_wait([this](const boost::system::error_code& ec) {
3440084047dSAppaRao Puli         if (ec == boost::asio::error::operation_aborted)
3450084047dSAppaRao Puli         {
3460084047dSAppaRao Puli             // Timer reset.
3470084047dSAppaRao Puli             return;
3480084047dSAppaRao Puli         }
3490084047dSAppaRao Puli         else if (ec)
3500084047dSAppaRao Puli         {
3510084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
3520084047dSAppaRao Puli                 "async wait error.");
3530084047dSAppaRao Puli             return;
3540084047dSAppaRao Puli         }
35590f2da3fSRichard Marian Thomaiyar         updateInProgress = true;
35690f2da3fSRichard Marian Thomaiyar         boost::asio::spawn(conn->get_io_context(),
35790f2da3fSRichard Marian Thomaiyar                            [this](boost::asio::yield_context yield) {
35890f2da3fSRichard Marian Thomaiyar                                // Stop and apply configuration for all objects
3590084047dSAppaRao Puli                                for (auto& srvMgrObj : srvMgrObjects)
3600084047dSAppaRao Puli                                {
3610084047dSAppaRao Puli                                    auto& srvObj = srvMgrObj.second;
3620084047dSAppaRao Puli                                    if (srvObj->updatedFlag)
3630084047dSAppaRao Puli                                    {
36490f2da3fSRichard Marian Thomaiyar                                        srvObj->stopAndApplyUnitConfig(yield);
3650084047dSAppaRao Puli                                    }
3660084047dSAppaRao Puli                                }
36790f2da3fSRichard Marian Thomaiyar                                // Do system reload
36890f2da3fSRichard Marian Thomaiyar                                systemdDaemonReload(conn, yield);
36990f2da3fSRichard Marian Thomaiyar                                // restart unit config.
37090f2da3fSRichard Marian Thomaiyar                                for (auto& srvMgrObj : srvMgrObjects)
37190f2da3fSRichard Marian Thomaiyar                                {
37290f2da3fSRichard Marian Thomaiyar                                    auto& srvObj = srvMgrObj.second;
37390f2da3fSRichard Marian Thomaiyar                                    if (srvObj->updatedFlag)
37490f2da3fSRichard Marian Thomaiyar                                    {
37590f2da3fSRichard Marian Thomaiyar                                        srvObj->restartUnitConfig(yield);
37690f2da3fSRichard Marian Thomaiyar                                    }
37790f2da3fSRichard Marian Thomaiyar                                }
37890f2da3fSRichard Marian Thomaiyar                                updateInProgress = false;
37990f2da3fSRichard Marian Thomaiyar                            });
3800084047dSAppaRao Puli     });
3810084047dSAppaRao Puli }
3820084047dSAppaRao Puli 
3830084047dSAppaRao Puli void ServiceConfig::registerProperties()
3840084047dSAppaRao Puli {
38590f2da3fSRichard Marian Thomaiyar     iface = server.add_interface(objPath, serviceConfigIntfName);
3860084047dSAppaRao Puli 
38790f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
38890f2da3fSRichard Marian Thomaiyar     {
3890084047dSAppaRao Puli         iface->register_property(
39090f2da3fSRichard Marian Thomaiyar             srvCfgPropPort, portNum,
39190f2da3fSRichard Marian Thomaiyar             [this](const uint16_t& req, uint16_t& res) {
39290f2da3fSRichard Marian Thomaiyar                 if (!internalSet)
39390f2da3fSRichard Marian Thomaiyar                 {
3940084047dSAppaRao Puli                     if (req == res)
3950084047dSAppaRao Puli                     {
3960084047dSAppaRao Puli                         return 1;
3970084047dSAppaRao Puli                     }
39890f2da3fSRichard Marian Thomaiyar                     if (updateInProgress)
39990f2da3fSRichard Marian Thomaiyar                     {
40090f2da3fSRichard Marian Thomaiyar                         return 0;
40190f2da3fSRichard Marian Thomaiyar                     }
4020084047dSAppaRao Puli                     portNum = req;
40390f2da3fSRichard Marian Thomaiyar                     updatedFlag |=
40490f2da3fSRichard Marian Thomaiyar                         (1 << static_cast<uint8_t>(UpdatedProp::port));
4050084047dSAppaRao Puli                     startServiceRestartTimer();
40690f2da3fSRichard Marian Thomaiyar                 }
40790f2da3fSRichard Marian Thomaiyar                 res = req;
40890f2da3fSRichard Marian Thomaiyar                 return 1;
40990f2da3fSRichard Marian Thomaiyar             });
41090f2da3fSRichard Marian Thomaiyar     }
41190f2da3fSRichard Marian Thomaiyar 
41290f2da3fSRichard Marian Thomaiyar     iface->register_property(
41390f2da3fSRichard Marian Thomaiyar         srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
41490f2da3fSRichard Marian Thomaiyar             if (!internalSet)
41590f2da3fSRichard Marian Thomaiyar             {
41690f2da3fSRichard Marian Thomaiyar                 if (req == res)
41790f2da3fSRichard Marian Thomaiyar                 {
41890f2da3fSRichard Marian Thomaiyar                     return 1;
41990f2da3fSRichard Marian Thomaiyar                 }
42090f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
42190f2da3fSRichard Marian Thomaiyar                 {
42290f2da3fSRichard Marian Thomaiyar                     return 0;
42390f2da3fSRichard Marian Thomaiyar                 }
42490f2da3fSRichard Marian Thomaiyar                 unitMaskedState = req;
42590f2da3fSRichard Marian Thomaiyar                 unitEnabledState = !unitMaskedState;
42690f2da3fSRichard Marian Thomaiyar                 unitRunningState = !unitMaskedState;
42790f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
42890f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
42990f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
43090f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
43190f2da3fSRichard Marian Thomaiyar                 internalSet = true;
43290f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropEnabled, unitEnabledState);
43390f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropRunning, unitRunningState);
43490f2da3fSRichard Marian Thomaiyar                 internalSet = false;
43590f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
43690f2da3fSRichard Marian Thomaiyar             }
4370084047dSAppaRao Puli             res = req;
4380084047dSAppaRao Puli             return 1;
4390084047dSAppaRao Puli         });
4400084047dSAppaRao Puli 
4410084047dSAppaRao Puli     iface->register_property(
44290f2da3fSRichard Marian Thomaiyar         srvCfgPropEnabled, unitEnabledState,
44390f2da3fSRichard Marian Thomaiyar         [this](const bool& req, bool& res) {
44490f2da3fSRichard Marian Thomaiyar             if (!internalSet)
44590f2da3fSRichard Marian Thomaiyar             {
4460084047dSAppaRao Puli                 if (req == res)
4470084047dSAppaRao Puli                 {
4480084047dSAppaRao Puli                     return 1;
4490084047dSAppaRao Puli                 }
45090f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
4510084047dSAppaRao Puli                 {
45290f2da3fSRichard Marian Thomaiyar                     return 0;
4530084047dSAppaRao Puli                 }
45490f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
45590f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
4560084047dSAppaRao Puli                     phosphor::logging::log<phosphor::logging::level::ERR>(
4570084047dSAppaRao Puli                         "Invalid value specified");
4580084047dSAppaRao Puli                     return -EINVAL;
4590084047dSAppaRao Puli                 }
46090f2da3fSRichard Marian Thomaiyar                 unitEnabledState = req;
46190f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
46290f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
4630084047dSAppaRao Puli                 startServiceRestartTimer();
46490f2da3fSRichard Marian Thomaiyar             }
46590f2da3fSRichard Marian Thomaiyar             res = req;
46690f2da3fSRichard Marian Thomaiyar             return 1;
46790f2da3fSRichard Marian Thomaiyar         });
46890f2da3fSRichard Marian Thomaiyar 
46990f2da3fSRichard Marian Thomaiyar     iface->register_property(
47090f2da3fSRichard Marian Thomaiyar         srvCfgPropRunning, unitRunningState,
47190f2da3fSRichard Marian Thomaiyar         [this](const bool& req, bool& res) {
47290f2da3fSRichard Marian Thomaiyar             if (!internalSet)
47390f2da3fSRichard Marian Thomaiyar             {
47490f2da3fSRichard Marian Thomaiyar                 if (req == res)
47590f2da3fSRichard Marian Thomaiyar                 {
47690f2da3fSRichard Marian Thomaiyar                     return 1;
47790f2da3fSRichard Marian Thomaiyar                 }
47890f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
47990f2da3fSRichard Marian Thomaiyar                 {
48090f2da3fSRichard Marian Thomaiyar                     return 0;
48190f2da3fSRichard Marian Thomaiyar                 }
48290f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
48390f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
48490f2da3fSRichard Marian Thomaiyar                     phosphor::logging::log<phosphor::logging::level::ERR>(
48590f2da3fSRichard Marian Thomaiyar                         "Invalid value specified");
48690f2da3fSRichard Marian Thomaiyar                     return -EINVAL;
48790f2da3fSRichard Marian Thomaiyar                 }
48890f2da3fSRichard Marian Thomaiyar                 unitRunningState = req;
48990f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
49090f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
49190f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
49290f2da3fSRichard Marian Thomaiyar             }
4930084047dSAppaRao Puli             res = req;
4940084047dSAppaRao Puli             return 1;
4950084047dSAppaRao Puli         });
4960084047dSAppaRao Puli 
4970084047dSAppaRao Puli     iface->initialize();
4980084047dSAppaRao Puli     return;
4990084047dSAppaRao Puli }
5000084047dSAppaRao Puli 
5010084047dSAppaRao Puli } // namespace service
5020084047dSAppaRao Puli } // namespace phosphor
503