xref: /openbmc/service-config-manager/src/srvcfg_manager.cpp (revision 33816cf9125737e9ec931961bad2924a6104c5bb)
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>
1890f2da3fSRichard Marian Thomaiyar #include <boost/asio/spawn.hpp>
190084047dSAppaRao Puli #include "srvcfg_manager.hpp"
200084047dSAppaRao Puli 
21*33816cf9SRichard Marian Thomaiyar extern std::unique_ptr<boost::asio::steady_timer> timer;
220084047dSAppaRao Puli extern std::map<std::string, std::shared_ptr<phosphor::service::ServiceConfig>>
230084047dSAppaRao Puli     srvMgrObjects;
2490f2da3fSRichard Marian Thomaiyar static bool updateInProgress = false;
250084047dSAppaRao Puli 
260084047dSAppaRao Puli namespace phosphor
270084047dSAppaRao Puli {
280084047dSAppaRao Puli namespace service
290084047dSAppaRao Puli {
300084047dSAppaRao Puli 
310084047dSAppaRao Puli static constexpr const char *overrideConfFileName = "override.conf";
320084047dSAppaRao Puli static constexpr const size_t restartTimeout = 15; // seconds
330084047dSAppaRao Puli 
340084047dSAppaRao Puli static constexpr const char *systemd1UnitBasePath =
350084047dSAppaRao Puli     "/org/freedesktop/systemd1/unit/";
360084047dSAppaRao Puli static constexpr const char *systemdOverrideUnitBasePath =
370084047dSAppaRao Puli     "/etc/systemd/system/";
380084047dSAppaRao Puli 
3990f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateSocketProperties(
4090f2da3fSRichard Marian Thomaiyar     const boost::container::flat_map<std::string, VariantType> &propertyMap)
410084047dSAppaRao Puli {
4290f2da3fSRichard Marian Thomaiyar     auto listenIt = propertyMap.find("Listen");
4390f2da3fSRichard Marian Thomaiyar     if (listenIt != propertyMap.end())
440084047dSAppaRao Puli     {
4590f2da3fSRichard Marian Thomaiyar         auto listenVal =
4690f2da3fSRichard Marian Thomaiyar             std::get<std::vector<std::tuple<std::string, std::string>>>(
4790f2da3fSRichard Marian Thomaiyar                 listenIt->second);
4890f2da3fSRichard Marian Thomaiyar         if (listenVal.size())
490084047dSAppaRao Puli         {
500084047dSAppaRao Puli             protocol = std::get<0>(listenVal[0]);
510084047dSAppaRao Puli             std::string port = std::get<1>(listenVal[0]);
520084047dSAppaRao Puli             auto tmp = std::stoul(port.substr(port.find_last_of(":") + 1),
530084047dSAppaRao Puli                                   nullptr, 10);
540084047dSAppaRao Puli             if (tmp > std::numeric_limits<uint16_t>::max())
550084047dSAppaRao Puli             {
560084047dSAppaRao Puli                 throw std::out_of_range("Out of range");
570084047dSAppaRao Puli             }
580084047dSAppaRao Puli             portNum = tmp;
5990f2da3fSRichard Marian Thomaiyar             if (iface && iface->is_initialized())
6090f2da3fSRichard Marian Thomaiyar             {
6190f2da3fSRichard Marian Thomaiyar                 internalSet = true;
6290f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropPort, portNum);
6390f2da3fSRichard Marian Thomaiyar                 internalSet = false;
6490f2da3fSRichard Marian Thomaiyar             }
6590f2da3fSRichard Marian Thomaiyar         }
6690f2da3fSRichard Marian Thomaiyar     }
6790f2da3fSRichard Marian Thomaiyar }
6890f2da3fSRichard Marian Thomaiyar 
6990f2da3fSRichard Marian Thomaiyar void ServiceConfig::updateServiceProperties(
7090f2da3fSRichard Marian Thomaiyar     const boost::container::flat_map<std::string, VariantType> &propertyMap)
7190f2da3fSRichard Marian Thomaiyar {
7290f2da3fSRichard Marian Thomaiyar     auto stateIt = propertyMap.find("UnitFileState");
7390f2da3fSRichard Marian Thomaiyar     if (stateIt != propertyMap.end())
7490f2da3fSRichard Marian Thomaiyar     {
7590f2da3fSRichard Marian Thomaiyar         stateValue = std::get<std::string>(stateIt->second);
7690f2da3fSRichard Marian Thomaiyar         unitEnabledState = unitMaskedState = false;
7790f2da3fSRichard Marian Thomaiyar         if (stateValue == stateMasked)
7890f2da3fSRichard Marian Thomaiyar         {
7990f2da3fSRichard Marian Thomaiyar             unitMaskedState = true;
8090f2da3fSRichard Marian Thomaiyar         }
8190f2da3fSRichard Marian Thomaiyar         else if (stateValue == stateEnabled)
8290f2da3fSRichard Marian Thomaiyar         {
8390f2da3fSRichard Marian Thomaiyar             unitEnabledState = true;
8490f2da3fSRichard Marian Thomaiyar         }
8590f2da3fSRichard Marian Thomaiyar         if (iface && iface->is_initialized())
8690f2da3fSRichard Marian Thomaiyar         {
8790f2da3fSRichard Marian Thomaiyar             internalSet = true;
8890f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropMasked, unitMaskedState);
8990f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropEnabled, unitEnabledState);
9090f2da3fSRichard Marian Thomaiyar             internalSet = false;
9190f2da3fSRichard Marian Thomaiyar         }
9290f2da3fSRichard Marian Thomaiyar     }
9390f2da3fSRichard Marian Thomaiyar     auto subStateIt = propertyMap.find("SubState");
9490f2da3fSRichard Marian Thomaiyar     if (subStateIt != propertyMap.end())
9590f2da3fSRichard Marian Thomaiyar     {
9690f2da3fSRichard Marian Thomaiyar         subStateValue = std::get<std::string>(subStateIt->second);
9790f2da3fSRichard Marian Thomaiyar         if (subStateValue == subStateRunning)
9890f2da3fSRichard Marian Thomaiyar         {
9990f2da3fSRichard Marian Thomaiyar             unitRunningState = true;
10090f2da3fSRichard Marian Thomaiyar         }
10190f2da3fSRichard Marian Thomaiyar         if (iface && iface->is_initialized())
10290f2da3fSRichard Marian Thomaiyar         {
10390f2da3fSRichard Marian Thomaiyar             internalSet = true;
10490f2da3fSRichard Marian Thomaiyar             iface->set_property(srvCfgPropRunning, unitRunningState);
10590f2da3fSRichard Marian Thomaiyar             internalSet = false;
10690f2da3fSRichard Marian Thomaiyar         }
10790f2da3fSRichard Marian Thomaiyar     }
10890f2da3fSRichard Marian Thomaiyar }
10990f2da3fSRichard Marian Thomaiyar 
11090f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties()
11190f2da3fSRichard Marian Thomaiyar {
11290f2da3fSRichard Marian Thomaiyar     conn->async_method_call(
11390f2da3fSRichard Marian Thomaiyar         [this](boost::system::error_code ec,
11490f2da3fSRichard Marian Thomaiyar                const boost::container::flat_map<std::string, VariantType>
11590f2da3fSRichard Marian Thomaiyar                    &propertyMap) {
11690f2da3fSRichard Marian Thomaiyar             if (ec)
11790f2da3fSRichard Marian Thomaiyar             {
11890f2da3fSRichard Marian Thomaiyar                 phosphor::logging::log<phosphor::logging::level::ERR>(
11990f2da3fSRichard Marian Thomaiyar                     "async_method_call error: Failed to service unit "
12090f2da3fSRichard Marian Thomaiyar                     "properties");
12190f2da3fSRichard Marian Thomaiyar                 return;
12290f2da3fSRichard Marian Thomaiyar             }
12390f2da3fSRichard Marian Thomaiyar             try
12490f2da3fSRichard Marian Thomaiyar             {
12590f2da3fSRichard Marian Thomaiyar                 updateServiceProperties(propertyMap);
12690f2da3fSRichard Marian Thomaiyar                 if (!socketObjectPath.empty())
12790f2da3fSRichard Marian Thomaiyar                 {
12890f2da3fSRichard Marian Thomaiyar                     conn->async_method_call(
12990f2da3fSRichard Marian Thomaiyar                         [this](boost::system::error_code ec,
13090f2da3fSRichard Marian Thomaiyar                                const boost::container::flat_map<
13190f2da3fSRichard Marian Thomaiyar                                    std::string, VariantType> &propertyMap) {
13290f2da3fSRichard Marian Thomaiyar                             if (ec)
13390f2da3fSRichard Marian Thomaiyar                             {
13490f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
13590f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
13690f2da3fSRichard Marian Thomaiyar                                     "async_method_call error: Failed to get "
13790f2da3fSRichard Marian Thomaiyar                                     "all property");
13890f2da3fSRichard Marian Thomaiyar                                 return;
13990f2da3fSRichard Marian Thomaiyar                             }
14090f2da3fSRichard Marian Thomaiyar                             try
14190f2da3fSRichard Marian Thomaiyar                             {
14290f2da3fSRichard Marian Thomaiyar                                 updateSocketProperties(propertyMap);
14390f2da3fSRichard Marian Thomaiyar                                 if (!iface)
14490f2da3fSRichard Marian Thomaiyar                                 {
14590f2da3fSRichard Marian Thomaiyar                                     registerProperties();
14690f2da3fSRichard Marian Thomaiyar                                 }
14790f2da3fSRichard Marian Thomaiyar                             }
14890f2da3fSRichard Marian Thomaiyar                             catch (const std::exception &e)
14990f2da3fSRichard Marian Thomaiyar                             {
15090f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
15190f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
15290f2da3fSRichard Marian Thomaiyar                                     "Exception in getting socket properties",
15390f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::entry("WHAT=%s",
15490f2da3fSRichard Marian Thomaiyar                                                              e.what()));
15590f2da3fSRichard Marian Thomaiyar                                 return;
15690f2da3fSRichard Marian Thomaiyar                             }
15790f2da3fSRichard Marian Thomaiyar                         },
15890f2da3fSRichard Marian Thomaiyar                         sysdService, socketObjectPath, dBusPropIntf,
15990f2da3fSRichard Marian Thomaiyar                         dBusGetAllMethod, sysdSocketIntf);
16090f2da3fSRichard Marian Thomaiyar                 }
16190f2da3fSRichard Marian Thomaiyar                 else if (!iface)
16290f2da3fSRichard Marian Thomaiyar                 {
16390f2da3fSRichard Marian Thomaiyar                     registerProperties();
16490f2da3fSRichard Marian Thomaiyar                 }
1650084047dSAppaRao Puli             }
1660084047dSAppaRao Puli             catch (const std::exception &e)
1670084047dSAppaRao Puli             {
1680084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
16990f2da3fSRichard Marian Thomaiyar                     "Exception in getting socket properties",
1700084047dSAppaRao Puli                     phosphor::logging::entry("WHAT=%s", e.what()));
1710084047dSAppaRao Puli                 return;
1720084047dSAppaRao Puli             }
1730084047dSAppaRao Puli         },
17490f2da3fSRichard Marian Thomaiyar         sysdService, serviceObjectPath, dBusPropIntf, dBusGetAllMethod,
17590f2da3fSRichard Marian Thomaiyar         sysdUnitIntf);
1760084047dSAppaRao Puli     return;
1770084047dSAppaRao Puli }
1780084047dSAppaRao Puli 
17990f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf()
1800084047dSAppaRao Puli {
18190f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
1820084047dSAppaRao Puli     {
18390f2da3fSRichard Marian Thomaiyar         std::string socketUnitName(instantiatedUnitName + ".socket");
1840084047dSAppaRao Puli         /// Check override socket directory exist, if not create it.
1850084047dSAppaRao Puli         std::experimental::filesystem::path ovrUnitFileDir(
1860084047dSAppaRao Puli             systemdOverrideUnitBasePath);
1870084047dSAppaRao Puli         ovrUnitFileDir += socketUnitName;
1880084047dSAppaRao Puli         ovrUnitFileDir += ".d";
1890084047dSAppaRao Puli         if (!std::experimental::filesystem::exists(ovrUnitFileDir))
1900084047dSAppaRao Puli         {
19190f2da3fSRichard Marian Thomaiyar             if (!std::experimental::filesystem::create_directories(
19290f2da3fSRichard Marian Thomaiyar                     ovrUnitFileDir))
1930084047dSAppaRao Puli             {
1940084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
1950084047dSAppaRao Puli                     "Unable to create the directory.",
1960084047dSAppaRao Puli                     phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
19790f2da3fSRichard Marian Thomaiyar                 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
19890f2da3fSRichard Marian Thomaiyar                                             Common::Error::InternalFailure>();
19990f2da3fSRichard Marian Thomaiyar             }
20090f2da3fSRichard Marian Thomaiyar         }
20190f2da3fSRichard Marian Thomaiyar         overrideConfDir = std::string(ovrUnitFileDir);
2020084047dSAppaRao Puli     }
2030084047dSAppaRao Puli }
2040084047dSAppaRao Puli 
20590f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig(
20690f2da3fSRichard Marian Thomaiyar     sdbusplus::asio::object_server &srv_,
20790f2da3fSRichard Marian Thomaiyar     std::shared_ptr<sdbusplus::asio::connection> &conn_,
20890f2da3fSRichard Marian Thomaiyar     const std::string &objPath_, const std::string &baseUnitName_,
20990f2da3fSRichard Marian Thomaiyar     const std::string &instanceName_, const std::string &serviceObjPath_,
21090f2da3fSRichard Marian Thomaiyar     const std::string &socketObjPath_) :
21190f2da3fSRichard Marian Thomaiyar     server(srv_),
21290f2da3fSRichard Marian Thomaiyar     conn(conn_), objPath(objPath_), baseUnitName(baseUnitName_),
21390f2da3fSRichard Marian Thomaiyar     instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
21490f2da3fSRichard Marian Thomaiyar     socketObjectPath(socketObjPath_)
21590f2da3fSRichard Marian Thomaiyar {
21690f2da3fSRichard Marian Thomaiyar     instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
2170084047dSAppaRao Puli     updatedFlag = 0;
21890f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
2190084047dSAppaRao Puli     return;
2200084047dSAppaRao Puli }
2210084047dSAppaRao Puli 
22290f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName()
2230084047dSAppaRao Puli {
22490f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".socket";
225e55cfd6eSAppaRao Puli }
226e55cfd6eSAppaRao Puli 
22790f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName()
22890f2da3fSRichard Marian Thomaiyar {
22990f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".service";
23090f2da3fSRichard Marian Thomaiyar }
23190f2da3fSRichard Marian Thomaiyar 
23290f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut()
23390f2da3fSRichard Marian Thomaiyar {
23490f2da3fSRichard Marian Thomaiyar     // return true  if state is masked & no request to update the maskedState
23590f2da3fSRichard Marian Thomaiyar     return (
23690f2da3fSRichard Marian Thomaiyar         stateValue == "masked" &&
23790f2da3fSRichard Marian Thomaiyar         !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
23890f2da3fSRichard Marian Thomaiyar }
23990f2da3fSRichard Marian Thomaiyar 
24090f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
24190f2da3fSRichard Marian Thomaiyar {
24290f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
24390f2da3fSRichard Marian Thomaiyar     {
24490f2da3fSRichard Marian Thomaiyar         // No updates / masked - Just return.
24590f2da3fSRichard Marian Thomaiyar         return;
24690f2da3fSRichard Marian Thomaiyar     }
2470084047dSAppaRao Puli     phosphor::logging::log<phosphor::logging::level::INFO>(
2480084047dSAppaRao Puli         "Applying new settings.",
2490084047dSAppaRao Puli         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
25090f2da3fSRichard Marian Thomaiyar     if (subStateValue == "running")
2510084047dSAppaRao Puli     {
25290f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
25390f2da3fSRichard Marian Thomaiyar         {
25490f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
25590f2da3fSRichard Marian Thomaiyar         }
25690f2da3fSRichard Marian Thomaiyar         systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
25790f2da3fSRichard Marian Thomaiyar     }
25890f2da3fSRichard Marian Thomaiyar 
25990f2da3fSRichard Marian Thomaiyar     if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
26090f2da3fSRichard Marian Thomaiyar     {
26190f2da3fSRichard Marian Thomaiyar         createSocketOverrideConf();
2620084047dSAppaRao Puli         // Create override config file and write data.
26390f2da3fSRichard Marian Thomaiyar         std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
2640084047dSAppaRao Puli         std::string tmpFile{ovrCfgFile + "_tmp"};
2650084047dSAppaRao Puli         std::ofstream cfgFile(tmpFile, std::ios::out);
2660084047dSAppaRao Puli         if (!cfgFile.good())
2670084047dSAppaRao Puli         {
2680084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
2690084047dSAppaRao Puli                 "Failed to open override.conf_tmp file");
2700084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
2710084047dSAppaRao Puli                                         Error::InternalFailure>();
2720084047dSAppaRao Puli         }
2730084047dSAppaRao Puli 
2740084047dSAppaRao Puli         // Write the socket header
2750084047dSAppaRao Puli         cfgFile << "[Socket]\n";
2760084047dSAppaRao Puli         // Listen
2770084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "="
2780084047dSAppaRao Puli                 << "\n";
2790084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "=" << portNum << "\n";
2800084047dSAppaRao Puli         cfgFile.close();
2810084047dSAppaRao Puli 
2820084047dSAppaRao Puli         if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
2830084047dSAppaRao Puli         {
2840084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
2850084047dSAppaRao Puli                 "Failed to rename tmp file as override.conf");
2860084047dSAppaRao Puli             std::remove(tmpFile.c_str());
2870084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
2880084047dSAppaRao Puli                                         Error::InternalFailure>();
2890084047dSAppaRao Puli         }
290e55cfd6eSAppaRao Puli     }
2910084047dSAppaRao Puli 
29290f2da3fSRichard Marian Thomaiyar     if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
29390f2da3fSRichard Marian Thomaiyar                        (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
294e55cfd6eSAppaRao Puli     {
29590f2da3fSRichard Marian Thomaiyar         std::vector<std::string> unitFiles;
29690f2da3fSRichard Marian Thomaiyar         if (socketObjectPath.empty())
29790f2da3fSRichard Marian Thomaiyar         {
29890f2da3fSRichard Marian Thomaiyar             unitFiles = {getServiceUnitName()};
299e55cfd6eSAppaRao Puli         }
30090f2da3fSRichard Marian Thomaiyar         else
301e55cfd6eSAppaRao Puli         {
30290f2da3fSRichard Marian Thomaiyar             unitFiles = {getSocketUnitName(), getServiceUnitName()};
30390f2da3fSRichard Marian Thomaiyar         }
30490f2da3fSRichard Marian Thomaiyar         systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
30590f2da3fSRichard Marian Thomaiyar                                     unitMaskedState, unitEnabledState);
30690f2da3fSRichard Marian Thomaiyar     }
30790f2da3fSRichard Marian Thomaiyar     return;
30890f2da3fSRichard Marian Thomaiyar }
30990f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
31090f2da3fSRichard Marian Thomaiyar {
31190f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
31290f2da3fSRichard Marian Thomaiyar     {
31390f2da3fSRichard Marian Thomaiyar         // No updates. Just return.
31490f2da3fSRichard Marian Thomaiyar         return;
3150084047dSAppaRao Puli     }
3160084047dSAppaRao Puli 
31790f2da3fSRichard Marian Thomaiyar     if (unitRunningState)
3180084047dSAppaRao Puli     {
31990f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
32090f2da3fSRichard Marian Thomaiyar         {
32190f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(),
32290f2da3fSRichard Marian Thomaiyar                               sysdRestartUnit);
3230084047dSAppaRao Puli         }
32490f2da3fSRichard Marian Thomaiyar         systemdUnitAction(conn, yield, getServiceUnitName(), sysdRestartUnit);
3250084047dSAppaRao Puli     }
3260084047dSAppaRao Puli 
3270084047dSAppaRao Puli     // Reset the flag
3280084047dSAppaRao Puli     updatedFlag = 0;
3290084047dSAppaRao Puli 
33090f2da3fSRichard Marian Thomaiyar     phosphor::logging::log<phosphor::logging::level::INFO>(
33190f2da3fSRichard Marian Thomaiyar         "Applied new settings",
33290f2da3fSRichard Marian Thomaiyar         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
3330084047dSAppaRao Puli 
33490f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
3350084047dSAppaRao Puli     return;
3360084047dSAppaRao Puli }
3370084047dSAppaRao Puli 
3380084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer()
3390084047dSAppaRao Puli {
340*33816cf9SRichard Marian Thomaiyar     timer->expires_after(std::chrono::seconds(restartTimeout));
3410084047dSAppaRao Puli     timer->async_wait([this](const boost::system::error_code &ec) {
3420084047dSAppaRao Puli         if (ec == boost::asio::error::operation_aborted)
3430084047dSAppaRao Puli         {
3440084047dSAppaRao Puli             // Timer reset.
3450084047dSAppaRao Puli             return;
3460084047dSAppaRao Puli         }
3470084047dSAppaRao Puli         else if (ec)
3480084047dSAppaRao Puli         {
3490084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
3500084047dSAppaRao Puli                 "async wait error.");
3510084047dSAppaRao Puli             return;
3520084047dSAppaRao Puli         }
35390f2da3fSRichard Marian Thomaiyar         updateInProgress = true;
35490f2da3fSRichard Marian Thomaiyar         boost::asio::spawn(conn->get_io_context(),
35590f2da3fSRichard Marian Thomaiyar                            [this](boost::asio::yield_context yield) {
35690f2da3fSRichard Marian Thomaiyar                                // Stop and apply configuration for all objects
3570084047dSAppaRao Puli                                for (auto &srvMgrObj : srvMgrObjects)
3580084047dSAppaRao Puli                                {
3590084047dSAppaRao Puli                                    auto &srvObj = srvMgrObj.second;
3600084047dSAppaRao Puli                                    if (srvObj->updatedFlag)
3610084047dSAppaRao Puli                                    {
36290f2da3fSRichard Marian Thomaiyar                                        srvObj->stopAndApplyUnitConfig(yield);
3630084047dSAppaRao Puli                                    }
3640084047dSAppaRao Puli                                }
36590f2da3fSRichard Marian Thomaiyar                                // Do system reload
36690f2da3fSRichard Marian Thomaiyar                                systemdDaemonReload(conn, yield);
36790f2da3fSRichard Marian Thomaiyar                                // restart unit config.
36890f2da3fSRichard Marian Thomaiyar                                for (auto &srvMgrObj : srvMgrObjects)
36990f2da3fSRichard Marian Thomaiyar                                {
37090f2da3fSRichard Marian Thomaiyar                                    auto &srvObj = srvMgrObj.second;
37190f2da3fSRichard Marian Thomaiyar                                    if (srvObj->updatedFlag)
37290f2da3fSRichard Marian Thomaiyar                                    {
37390f2da3fSRichard Marian Thomaiyar                                        srvObj->restartUnitConfig(yield);
37490f2da3fSRichard Marian Thomaiyar                                    }
37590f2da3fSRichard Marian Thomaiyar                                }
37690f2da3fSRichard Marian Thomaiyar                                updateInProgress = false;
37790f2da3fSRichard Marian Thomaiyar                            });
3780084047dSAppaRao Puli     });
3790084047dSAppaRao Puli }
3800084047dSAppaRao Puli 
3810084047dSAppaRao Puli void ServiceConfig::registerProperties()
3820084047dSAppaRao Puli {
38390f2da3fSRichard Marian Thomaiyar     iface = server.add_interface(objPath, serviceConfigIntfName);
3840084047dSAppaRao Puli 
38590f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
38690f2da3fSRichard Marian Thomaiyar     {
3870084047dSAppaRao Puli         iface->register_property(
38890f2da3fSRichard Marian Thomaiyar             srvCfgPropPort, portNum,
38990f2da3fSRichard Marian Thomaiyar             [this](const uint16_t &req, uint16_t &res) {
39090f2da3fSRichard Marian Thomaiyar                 if (!internalSet)
39190f2da3fSRichard Marian Thomaiyar                 {
3920084047dSAppaRao Puli                     if (req == res)
3930084047dSAppaRao Puli                     {
3940084047dSAppaRao Puli                         return 1;
3950084047dSAppaRao Puli                     }
39690f2da3fSRichard Marian Thomaiyar                     if (updateInProgress)
39790f2da3fSRichard Marian Thomaiyar                     {
39890f2da3fSRichard Marian Thomaiyar                         return 0;
39990f2da3fSRichard Marian Thomaiyar                     }
4000084047dSAppaRao Puli                     portNum = req;
40190f2da3fSRichard Marian Thomaiyar                     updatedFlag |=
40290f2da3fSRichard Marian Thomaiyar                         (1 << static_cast<uint8_t>(UpdatedProp::port));
4030084047dSAppaRao Puli                     startServiceRestartTimer();
40490f2da3fSRichard Marian Thomaiyar                 }
40590f2da3fSRichard Marian Thomaiyar                 res = req;
40690f2da3fSRichard Marian Thomaiyar                 return 1;
40790f2da3fSRichard Marian Thomaiyar             });
40890f2da3fSRichard Marian Thomaiyar     }
40990f2da3fSRichard Marian Thomaiyar 
41090f2da3fSRichard Marian Thomaiyar     iface->register_property(
41190f2da3fSRichard Marian Thomaiyar         srvCfgPropMasked, unitMaskedState, [this](const bool &req, bool &res) {
41290f2da3fSRichard Marian Thomaiyar             if (!internalSet)
41390f2da3fSRichard Marian Thomaiyar             {
41490f2da3fSRichard Marian Thomaiyar                 if (req == res)
41590f2da3fSRichard Marian Thomaiyar                 {
41690f2da3fSRichard Marian Thomaiyar                     return 1;
41790f2da3fSRichard Marian Thomaiyar                 }
41890f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
41990f2da3fSRichard Marian Thomaiyar                 {
42090f2da3fSRichard Marian Thomaiyar                     return 0;
42190f2da3fSRichard Marian Thomaiyar                 }
42290f2da3fSRichard Marian Thomaiyar                 unitMaskedState = req;
42390f2da3fSRichard Marian Thomaiyar                 unitEnabledState = !unitMaskedState;
42490f2da3fSRichard Marian Thomaiyar                 unitRunningState = !unitMaskedState;
42590f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
42690f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
42790f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
42890f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
42990f2da3fSRichard Marian Thomaiyar                 internalSet = true;
43090f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropEnabled, unitEnabledState);
43190f2da3fSRichard Marian Thomaiyar                 iface->set_property(srvCfgPropRunning, unitRunningState);
43290f2da3fSRichard Marian Thomaiyar                 internalSet = false;
43390f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
43490f2da3fSRichard Marian Thomaiyar             }
4350084047dSAppaRao Puli             res = req;
4360084047dSAppaRao Puli             return 1;
4370084047dSAppaRao Puli         });
4380084047dSAppaRao Puli 
4390084047dSAppaRao Puli     iface->register_property(
44090f2da3fSRichard Marian Thomaiyar         srvCfgPropEnabled, unitEnabledState,
44190f2da3fSRichard Marian Thomaiyar         [this](const bool &req, bool &res) {
44290f2da3fSRichard Marian Thomaiyar             if (!internalSet)
44390f2da3fSRichard Marian Thomaiyar             {
4440084047dSAppaRao Puli                 if (req == res)
4450084047dSAppaRao Puli                 {
4460084047dSAppaRao Puli                     return 1;
4470084047dSAppaRao Puli                 }
44890f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
4490084047dSAppaRao Puli                 {
45090f2da3fSRichard Marian Thomaiyar                     return 0;
4510084047dSAppaRao Puli                 }
45290f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
45390f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
4540084047dSAppaRao Puli                     phosphor::logging::log<phosphor::logging::level::ERR>(
4550084047dSAppaRao Puli                         "Invalid value specified");
4560084047dSAppaRao Puli                     return -EINVAL;
4570084047dSAppaRao Puli                 }
45890f2da3fSRichard Marian Thomaiyar                 unitEnabledState = req;
45990f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
46090f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
4610084047dSAppaRao Puli                 startServiceRestartTimer();
46290f2da3fSRichard Marian Thomaiyar             }
46390f2da3fSRichard Marian Thomaiyar             res = req;
46490f2da3fSRichard Marian Thomaiyar             return 1;
46590f2da3fSRichard Marian Thomaiyar         });
46690f2da3fSRichard Marian Thomaiyar 
46790f2da3fSRichard Marian Thomaiyar     iface->register_property(
46890f2da3fSRichard Marian Thomaiyar         srvCfgPropRunning, unitRunningState,
46990f2da3fSRichard Marian Thomaiyar         [this](const bool &req, bool &res) {
47090f2da3fSRichard Marian Thomaiyar             if (!internalSet)
47190f2da3fSRichard Marian Thomaiyar             {
47290f2da3fSRichard Marian Thomaiyar                 if (req == res)
47390f2da3fSRichard Marian Thomaiyar                 {
47490f2da3fSRichard Marian Thomaiyar                     return 1;
47590f2da3fSRichard Marian Thomaiyar                 }
47690f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
47790f2da3fSRichard Marian Thomaiyar                 {
47890f2da3fSRichard Marian Thomaiyar                     return 0;
47990f2da3fSRichard Marian Thomaiyar                 }
48090f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
48190f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
48290f2da3fSRichard Marian Thomaiyar                     phosphor::logging::log<phosphor::logging::level::ERR>(
48390f2da3fSRichard Marian Thomaiyar                         "Invalid value specified");
48490f2da3fSRichard Marian Thomaiyar                     return -EINVAL;
48590f2da3fSRichard Marian Thomaiyar                 }
48690f2da3fSRichard Marian Thomaiyar                 unitRunningState = req;
48790f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
48890f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
48990f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
49090f2da3fSRichard Marian Thomaiyar             }
4910084047dSAppaRao Puli             res = req;
4920084047dSAppaRao Puli             return 1;
4930084047dSAppaRao Puli         });
4940084047dSAppaRao Puli 
4950084047dSAppaRao Puli     iface->initialize();
4960084047dSAppaRao Puli     return;
4970084047dSAppaRao Puli }
4980084047dSAppaRao Puli 
4990084047dSAppaRao Puli } // namespace service
5000084047dSAppaRao Puli } // namespace phosphor
501