xref: /openbmc/service-config-manager/src/srvcfg_manager.cpp (revision a19b509352cc7d9fcacf345f81163bf6998ec7b4)
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 */
16ee853eb2SAppaRao Puli #include "srvcfg_manager.hpp"
17ee853eb2SAppaRao Puli 
18ee853eb2SAppaRao Puli #include <boost/asio/spawn.hpp>
19ee853eb2SAppaRao 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;
6183241c09STom Joseph             if (sockAttrIface && sockAttrIface->is_initialized())
6290f2da3fSRichard Marian Thomaiyar             {
6390f2da3fSRichard Marian Thomaiyar                 internalSet = true;
6483241c09STom Joseph                 sockAttrIface->set_property(sockAttrPropPort, 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         }
8783241c09STom Joseph         if (srvCfgIface && srvCfgIface->is_initialized())
8890f2da3fSRichard Marian Thomaiyar         {
8990f2da3fSRichard Marian Thomaiyar             internalSet = true;
9083241c09STom Joseph             srvCfgIface->set_property(srvCfgPropMasked, unitMaskedState);
9183241c09STom Joseph             srvCfgIface->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);
99*a19b5093SGeorge Liu         if (subStateValue == subStateRunning ||
100*a19b5093SGeorge Liu             subStateValue == subStateListening)
10190f2da3fSRichard Marian Thomaiyar         {
10290f2da3fSRichard Marian Thomaiyar             unitRunningState = true;
10390f2da3fSRichard Marian Thomaiyar         }
10483241c09STom Joseph         if (srvCfgIface && srvCfgIface->is_initialized())
10590f2da3fSRichard Marian Thomaiyar         {
10690f2da3fSRichard Marian Thomaiyar             internalSet = true;
10783241c09STom Joseph             srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
10890f2da3fSRichard Marian Thomaiyar             internalSet = false;
10990f2da3fSRichard Marian Thomaiyar         }
11090f2da3fSRichard Marian Thomaiyar     }
11190f2da3fSRichard Marian Thomaiyar }
11290f2da3fSRichard Marian Thomaiyar 
11390f2da3fSRichard Marian Thomaiyar void ServiceConfig::queryAndUpdateProperties()
11490f2da3fSRichard Marian Thomaiyar {
115*a19b5093SGeorge Liu     std::string objectPath =
116*a19b5093SGeorge Liu         isDropBearService ? socketObjectPath : serviceObjectPath;
117*a19b5093SGeorge Liu     if (objectPath.empty())
118*a19b5093SGeorge Liu     {
119*a19b5093SGeorge Liu         return;
120*a19b5093SGeorge Liu     }
121*a19b5093SGeorge Liu 
12290f2da3fSRichard Marian Thomaiyar     conn->async_method_call(
12390f2da3fSRichard Marian Thomaiyar         [this](boost::system::error_code ec,
124ee853eb2SAppaRao Puli                const boost::container::flat_map<std::string, VariantType>&
125ee853eb2SAppaRao Puli                    propertyMap) {
12690f2da3fSRichard Marian Thomaiyar             if (ec)
12790f2da3fSRichard Marian Thomaiyar             {
12890f2da3fSRichard Marian Thomaiyar                 phosphor::logging::log<phosphor::logging::level::ERR>(
12990f2da3fSRichard Marian Thomaiyar                     "async_method_call error: Failed to service unit "
13090f2da3fSRichard Marian Thomaiyar                     "properties");
13190f2da3fSRichard Marian Thomaiyar                 return;
13290f2da3fSRichard Marian Thomaiyar             }
13390f2da3fSRichard Marian Thomaiyar             try
13490f2da3fSRichard Marian Thomaiyar             {
13590f2da3fSRichard Marian Thomaiyar                 updateServiceProperties(propertyMap);
13690f2da3fSRichard Marian Thomaiyar                 if (!socketObjectPath.empty())
13790f2da3fSRichard Marian Thomaiyar                 {
13890f2da3fSRichard Marian Thomaiyar                     conn->async_method_call(
13990f2da3fSRichard Marian Thomaiyar                         [this](boost::system::error_code ec,
14090f2da3fSRichard Marian Thomaiyar                                const boost::container::flat_map<
14190f2da3fSRichard Marian Thomaiyar                                    std::string, VariantType>& propertyMap) {
14290f2da3fSRichard Marian Thomaiyar                             if (ec)
14390f2da3fSRichard Marian Thomaiyar                             {
14490f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
14590f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
14690f2da3fSRichard Marian Thomaiyar                                     "async_method_call error: Failed to get "
14790f2da3fSRichard Marian Thomaiyar                                     "all property");
14890f2da3fSRichard Marian Thomaiyar                                 return;
14990f2da3fSRichard Marian Thomaiyar                             }
15090f2da3fSRichard Marian Thomaiyar                             try
15190f2da3fSRichard Marian Thomaiyar                             {
15290f2da3fSRichard Marian Thomaiyar                                 updateSocketProperties(propertyMap);
15383241c09STom Joseph                                 if (!srvCfgIface)
15490f2da3fSRichard Marian Thomaiyar                                 {
15590f2da3fSRichard Marian Thomaiyar                                     registerProperties();
15690f2da3fSRichard Marian Thomaiyar                                 }
15790f2da3fSRichard Marian Thomaiyar                             }
15890f2da3fSRichard Marian Thomaiyar                             catch (const std::exception& e)
15990f2da3fSRichard Marian Thomaiyar                             {
16090f2da3fSRichard Marian Thomaiyar                                 phosphor::logging::log<
16190f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::level::ERR>(
16290f2da3fSRichard Marian Thomaiyar                                     "Exception in getting socket properties",
16390f2da3fSRichard Marian Thomaiyar                                     phosphor::logging::entry("WHAT=%s",
16490f2da3fSRichard Marian Thomaiyar                                                              e.what()));
16590f2da3fSRichard Marian Thomaiyar                                 return;
16690f2da3fSRichard Marian Thomaiyar                             }
16790f2da3fSRichard Marian Thomaiyar                         },
16890f2da3fSRichard Marian Thomaiyar                         sysdService, socketObjectPath, dBusPropIntf,
16990f2da3fSRichard Marian Thomaiyar                         dBusGetAllMethod, sysdSocketIntf);
17090f2da3fSRichard Marian Thomaiyar                 }
17183241c09STom Joseph                 else if (!srvCfgIface)
17290f2da3fSRichard Marian Thomaiyar                 {
17390f2da3fSRichard Marian Thomaiyar                     registerProperties();
17490f2da3fSRichard Marian Thomaiyar                 }
1750084047dSAppaRao Puli             }
1760084047dSAppaRao Puli             catch (const std::exception& e)
1770084047dSAppaRao Puli             {
1780084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
17990f2da3fSRichard Marian Thomaiyar                     "Exception in getting socket properties",
1800084047dSAppaRao Puli                     phosphor::logging::entry("WHAT=%s", e.what()));
1810084047dSAppaRao Puli                 return;
1820084047dSAppaRao Puli             }
1830084047dSAppaRao Puli         },
184*a19b5093SGeorge Liu         sysdService, objectPath, dBusPropIntf, dBusGetAllMethod, sysdUnitIntf);
1850084047dSAppaRao Puli     return;
1860084047dSAppaRao Puli }
1870084047dSAppaRao Puli 
18890f2da3fSRichard Marian Thomaiyar void ServiceConfig::createSocketOverrideConf()
1890084047dSAppaRao Puli {
19090f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
1910084047dSAppaRao Puli     {
19290f2da3fSRichard Marian Thomaiyar         std::string socketUnitName(instantiatedUnitName + ".socket");
1930084047dSAppaRao Puli         /// Check override socket directory exist, if not create it.
19482e9557eSTom Joseph         std::filesystem::path ovrUnitFileDir(systemdOverrideUnitBasePath);
1950084047dSAppaRao Puli         ovrUnitFileDir += socketUnitName;
1960084047dSAppaRao Puli         ovrUnitFileDir += ".d";
19782e9557eSTom Joseph         if (!std::filesystem::exists(ovrUnitFileDir))
1980084047dSAppaRao Puli         {
19982e9557eSTom Joseph             if (!std::filesystem::create_directories(ovrUnitFileDir))
2000084047dSAppaRao Puli             {
2010084047dSAppaRao Puli                 phosphor::logging::log<phosphor::logging::level::ERR>(
2020084047dSAppaRao Puli                     "Unable to create the directory.",
2030084047dSAppaRao Puli                     phosphor::logging::entry("DIR=%s", ovrUnitFileDir.c_str()));
20490f2da3fSRichard Marian Thomaiyar                 phosphor::logging::elog<sdbusplus::xyz::openbmc_project::
20590f2da3fSRichard Marian Thomaiyar                                             Common::Error::InternalFailure>();
20690f2da3fSRichard Marian Thomaiyar             }
20790f2da3fSRichard Marian Thomaiyar         }
20890f2da3fSRichard Marian Thomaiyar         overrideConfDir = std::string(ovrUnitFileDir);
2090084047dSAppaRao Puli     }
2100084047dSAppaRao Puli }
2110084047dSAppaRao Puli 
21290f2da3fSRichard Marian Thomaiyar ServiceConfig::ServiceConfig(
21390f2da3fSRichard Marian Thomaiyar     sdbusplus::asio::object_server& srv_,
21490f2da3fSRichard Marian Thomaiyar     std::shared_ptr<sdbusplus::asio::connection>& conn_,
21590f2da3fSRichard Marian Thomaiyar     const std::string& objPath_, const std::string& baseUnitName_,
21690f2da3fSRichard Marian Thomaiyar     const std::string& instanceName_, const std::string& serviceObjPath_,
21790f2da3fSRichard Marian Thomaiyar     const std::string& socketObjPath_) :
21882e9557eSTom Joseph     conn(conn_),
21982e9557eSTom Joseph     server(srv_), objPath(objPath_), baseUnitName(baseUnitName_),
22090f2da3fSRichard Marian Thomaiyar     instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
22190f2da3fSRichard Marian Thomaiyar     socketObjectPath(socketObjPath_)
22290f2da3fSRichard Marian Thomaiyar {
223*a19b5093SGeorge Liu     if (baseUnitName == "dropbear")
224*a19b5093SGeorge Liu     {
225*a19b5093SGeorge Liu         isDropBearService = true;
226*a19b5093SGeorge Liu     }
22790f2da3fSRichard Marian Thomaiyar     instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
2280084047dSAppaRao Puli     updatedFlag = 0;
22990f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
2300084047dSAppaRao Puli     return;
2310084047dSAppaRao Puli }
2320084047dSAppaRao Puli 
23390f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getSocketUnitName()
2340084047dSAppaRao Puli {
23590f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".socket";
236e55cfd6eSAppaRao Puli }
237e55cfd6eSAppaRao Puli 
23890f2da3fSRichard Marian Thomaiyar std::string ServiceConfig::getServiceUnitName()
23990f2da3fSRichard Marian Thomaiyar {
24090f2da3fSRichard Marian Thomaiyar     return instantiatedUnitName + ".service";
24190f2da3fSRichard Marian Thomaiyar }
24290f2da3fSRichard Marian Thomaiyar 
24390f2da3fSRichard Marian Thomaiyar bool ServiceConfig::isMaskedOut()
24490f2da3fSRichard Marian Thomaiyar {
24590f2da3fSRichard Marian Thomaiyar     // return true  if state is masked & no request to update the maskedState
24690f2da3fSRichard Marian Thomaiyar     return (
24790f2da3fSRichard Marian Thomaiyar         stateValue == "masked" &&
24890f2da3fSRichard Marian Thomaiyar         !(updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::maskedState))));
24990f2da3fSRichard Marian Thomaiyar }
25090f2da3fSRichard Marian Thomaiyar 
25190f2da3fSRichard Marian Thomaiyar void ServiceConfig::stopAndApplyUnitConfig(boost::asio::yield_context yield)
25290f2da3fSRichard Marian Thomaiyar {
25390f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
25490f2da3fSRichard Marian Thomaiyar     {
25590f2da3fSRichard Marian Thomaiyar         // No updates / masked - Just return.
25690f2da3fSRichard Marian Thomaiyar         return;
25790f2da3fSRichard Marian Thomaiyar     }
2580084047dSAppaRao Puli     phosphor::logging::log<phosphor::logging::level::INFO>(
2590084047dSAppaRao Puli         "Applying new settings.",
2600084047dSAppaRao Puli         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
261*a19b5093SGeorge Liu     if (subStateValue == subStateRunning || subStateValue == subStateListening)
2620084047dSAppaRao Puli     {
26390f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
26490f2da3fSRichard Marian Thomaiyar         {
26590f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
26690f2da3fSRichard Marian Thomaiyar         }
267*a19b5093SGeorge Liu         if (!isDropBearService)
268*a19b5093SGeorge Liu         {
26990f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
27090f2da3fSRichard Marian Thomaiyar         }
271*a19b5093SGeorge Liu         else
272*a19b5093SGeorge Liu         {
273*a19b5093SGeorge Liu             // Get the ListUnits property, find all the services of
274*a19b5093SGeorge Liu             // `dropbear@<ip><port>.service` and stop the service through
275*a19b5093SGeorge Liu             // the systemdUnitAction method
276*a19b5093SGeorge Liu             boost::system::error_code ec;
277*a19b5093SGeorge Liu             auto listUnits =
278*a19b5093SGeorge Liu                 conn->yield_method_call<std::vector<ListUnitsType>>(
279*a19b5093SGeorge Liu                     yield, ec, sysdService, sysdObjPath, sysdMgrIntf,
280*a19b5093SGeorge Liu                     "ListUnits");
281*a19b5093SGeorge Liu 
282*a19b5093SGeorge Liu             checkAndThrowInternalFailure(
283*a19b5093SGeorge Liu                 ec, "yield_method_call error: ListUnits failed");
284*a19b5093SGeorge Liu 
285*a19b5093SGeorge Liu             for (const auto& unit : listUnits)
286*a19b5093SGeorge Liu             {
287*a19b5093SGeorge Liu                 const auto& service =
288*a19b5093SGeorge Liu                     std::get<static_cast<int>(ListUnitElements::name)>(unit);
289*a19b5093SGeorge Liu                 const auto& status =
290*a19b5093SGeorge Liu                     std::get<static_cast<int>(ListUnitElements::subState)>(
291*a19b5093SGeorge Liu                         unit);
292*a19b5093SGeorge Liu                 if (service.find("dropbear@") != std::string::npos &&
293*a19b5093SGeorge Liu                     service.find(".service") != std::string::npos &&
294*a19b5093SGeorge Liu                     status == subStateRunning)
295*a19b5093SGeorge Liu                 {
296*a19b5093SGeorge Liu                     systemdUnitAction(conn, yield, service, sysdStopUnit);
297*a19b5093SGeorge Liu                 }
298*a19b5093SGeorge Liu             }
299*a19b5093SGeorge Liu         }
300*a19b5093SGeorge Liu     }
30190f2da3fSRichard Marian Thomaiyar 
30290f2da3fSRichard Marian Thomaiyar     if (updatedFlag & (1 << static_cast<uint8_t>(UpdatedProp::port)))
30390f2da3fSRichard Marian Thomaiyar     {
30490f2da3fSRichard Marian Thomaiyar         createSocketOverrideConf();
3050084047dSAppaRao Puli         // Create override config file and write data.
30690f2da3fSRichard Marian Thomaiyar         std::string ovrCfgFile{overrideConfDir + "/" + overrideConfFileName};
3070084047dSAppaRao Puli         std::string tmpFile{ovrCfgFile + "_tmp"};
3080084047dSAppaRao Puli         std::ofstream cfgFile(tmpFile, std::ios::out);
3090084047dSAppaRao Puli         if (!cfgFile.good())
3100084047dSAppaRao Puli         {
3110084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
3120084047dSAppaRao Puli                 "Failed to open override.conf_tmp file");
3130084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
3140084047dSAppaRao Puli                                         Error::InternalFailure>();
3150084047dSAppaRao Puli         }
3160084047dSAppaRao Puli 
3170084047dSAppaRao Puli         // Write the socket header
3180084047dSAppaRao Puli         cfgFile << "[Socket]\n";
3190084047dSAppaRao Puli         // Listen
3200084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "="
3210084047dSAppaRao Puli                 << "\n";
3220084047dSAppaRao Puli         cfgFile << "Listen" << protocol << "=" << portNum << "\n";
3230084047dSAppaRao Puli         cfgFile.close();
3240084047dSAppaRao Puli 
3250084047dSAppaRao Puli         if (std::rename(tmpFile.c_str(), ovrCfgFile.c_str()) != 0)
3260084047dSAppaRao Puli         {
3270084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
3280084047dSAppaRao Puli                 "Failed to rename tmp file as override.conf");
3290084047dSAppaRao Puli             std::remove(tmpFile.c_str());
3300084047dSAppaRao Puli             phosphor::logging::elog<sdbusplus::xyz::openbmc_project::Common::
3310084047dSAppaRao Puli                                         Error::InternalFailure>();
3320084047dSAppaRao Puli         }
333e55cfd6eSAppaRao Puli     }
3340084047dSAppaRao Puli 
33590f2da3fSRichard Marian Thomaiyar     if (updatedFlag & ((1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
33690f2da3fSRichard Marian Thomaiyar                        (1 << static_cast<uint8_t>(UpdatedProp::enabledState))))
337e55cfd6eSAppaRao Puli     {
33890f2da3fSRichard Marian Thomaiyar         std::vector<std::string> unitFiles;
33990f2da3fSRichard Marian Thomaiyar         if (socketObjectPath.empty())
34090f2da3fSRichard Marian Thomaiyar         {
34190f2da3fSRichard Marian Thomaiyar             unitFiles = {getServiceUnitName()};
342e55cfd6eSAppaRao Puli         }
343*a19b5093SGeorge Liu         else if (!socketObjectPath.empty() && isDropBearService)
344*a19b5093SGeorge Liu         {
345*a19b5093SGeorge Liu             unitFiles = {getSocketUnitName()};
346*a19b5093SGeorge Liu         }
34790f2da3fSRichard Marian Thomaiyar         else
348e55cfd6eSAppaRao Puli         {
34990f2da3fSRichard Marian Thomaiyar             unitFiles = {getSocketUnitName(), getServiceUnitName()};
35090f2da3fSRichard Marian Thomaiyar         }
35190f2da3fSRichard Marian Thomaiyar         systemdUnitFilesStateChange(conn, yield, unitFiles, stateValue,
35290f2da3fSRichard Marian Thomaiyar                                     unitMaskedState, unitEnabledState);
35390f2da3fSRichard Marian Thomaiyar     }
35490f2da3fSRichard Marian Thomaiyar     return;
35590f2da3fSRichard Marian Thomaiyar }
35690f2da3fSRichard Marian Thomaiyar void ServiceConfig::restartUnitConfig(boost::asio::yield_context yield)
35790f2da3fSRichard Marian Thomaiyar {
35890f2da3fSRichard Marian Thomaiyar     if (!updatedFlag || isMaskedOut())
35990f2da3fSRichard Marian Thomaiyar     {
36090f2da3fSRichard Marian Thomaiyar         // No updates. Just return.
36190f2da3fSRichard Marian Thomaiyar         return;
3620084047dSAppaRao Puli     }
3630084047dSAppaRao Puli 
36490f2da3fSRichard Marian Thomaiyar     if (unitRunningState)
3650084047dSAppaRao Puli     {
36690f2da3fSRichard Marian Thomaiyar         if (!socketObjectPath.empty())
36790f2da3fSRichard Marian Thomaiyar         {
36890f2da3fSRichard Marian Thomaiyar             systemdUnitAction(conn, yield, getSocketUnitName(),
36990f2da3fSRichard Marian Thomaiyar                               sysdRestartUnit);
3700084047dSAppaRao Puli         }
371*a19b5093SGeorge Liu         if (!isDropBearService)
372*a19b5093SGeorge Liu         {
373*a19b5093SGeorge Liu             systemdUnitAction(conn, yield, getServiceUnitName(),
374*a19b5093SGeorge Liu                               sysdRestartUnit);
375*a19b5093SGeorge Liu         }
3760084047dSAppaRao Puli     }
3770084047dSAppaRao Puli 
3780084047dSAppaRao Puli     // Reset the flag
3790084047dSAppaRao Puli     updatedFlag = 0;
3800084047dSAppaRao Puli 
38190f2da3fSRichard Marian Thomaiyar     phosphor::logging::log<phosphor::logging::level::INFO>(
38290f2da3fSRichard Marian Thomaiyar         "Applied new settings",
38390f2da3fSRichard Marian Thomaiyar         phosphor::logging::entry("OBJPATH=%s", objPath.c_str()));
3840084047dSAppaRao Puli 
38590f2da3fSRichard Marian Thomaiyar     queryAndUpdateProperties();
3860084047dSAppaRao Puli     return;
3870084047dSAppaRao Puli }
3880084047dSAppaRao Puli 
3890084047dSAppaRao Puli void ServiceConfig::startServiceRestartTimer()
3900084047dSAppaRao Puli {
39133816cf9SRichard Marian Thomaiyar     timer->expires_after(std::chrono::seconds(restartTimeout));
3920084047dSAppaRao Puli     timer->async_wait([this](const boost::system::error_code& ec) {
3930084047dSAppaRao Puli         if (ec == boost::asio::error::operation_aborted)
3940084047dSAppaRao Puli         {
3950084047dSAppaRao Puli             // Timer reset.
3960084047dSAppaRao Puli             return;
3970084047dSAppaRao Puli         }
3980084047dSAppaRao Puli         else if (ec)
3990084047dSAppaRao Puli         {
4000084047dSAppaRao Puli             phosphor::logging::log<phosphor::logging::level::ERR>(
4010084047dSAppaRao Puli                 "async wait error.");
4020084047dSAppaRao Puli             return;
4030084047dSAppaRao Puli         }
40490f2da3fSRichard Marian Thomaiyar         updateInProgress = true;
40590f2da3fSRichard Marian Thomaiyar         boost::asio::spawn(conn->get_io_context(),
40690f2da3fSRichard Marian Thomaiyar                            [this](boost::asio::yield_context yield) {
40790f2da3fSRichard Marian Thomaiyar                                // Stop and apply configuration for all objects
4080084047dSAppaRao Puli                                for (auto& srvMgrObj : srvMgrObjects)
4090084047dSAppaRao Puli                                {
4100084047dSAppaRao Puli                                    auto& srvObj = srvMgrObj.second;
4110084047dSAppaRao Puli                                    if (srvObj->updatedFlag)
4120084047dSAppaRao Puli                                    {
41390f2da3fSRichard Marian Thomaiyar                                        srvObj->stopAndApplyUnitConfig(yield);
4140084047dSAppaRao Puli                                    }
4150084047dSAppaRao Puli                                }
41690f2da3fSRichard Marian Thomaiyar                                // Do system reload
41790f2da3fSRichard Marian Thomaiyar                                systemdDaemonReload(conn, yield);
41890f2da3fSRichard Marian Thomaiyar                                // restart unit config.
41990f2da3fSRichard Marian Thomaiyar                                for (auto& srvMgrObj : srvMgrObjects)
42090f2da3fSRichard Marian Thomaiyar                                {
42190f2da3fSRichard Marian Thomaiyar                                    auto& srvObj = srvMgrObj.second;
42290f2da3fSRichard Marian Thomaiyar                                    if (srvObj->updatedFlag)
42390f2da3fSRichard Marian Thomaiyar                                    {
42490f2da3fSRichard Marian Thomaiyar                                        srvObj->restartUnitConfig(yield);
42590f2da3fSRichard Marian Thomaiyar                                    }
42690f2da3fSRichard Marian Thomaiyar                                }
42790f2da3fSRichard Marian Thomaiyar                                updateInProgress = false;
42890f2da3fSRichard Marian Thomaiyar                            });
4290084047dSAppaRao Puli     });
4300084047dSAppaRao Puli }
4310084047dSAppaRao Puli 
4320084047dSAppaRao Puli void ServiceConfig::registerProperties()
4330084047dSAppaRao Puli {
43483241c09STom Joseph     srvCfgIface = server.add_interface(objPath, serviceConfigIntfName);
4350084047dSAppaRao Puli 
43690f2da3fSRichard Marian Thomaiyar     if (!socketObjectPath.empty())
43790f2da3fSRichard Marian Thomaiyar     {
43883241c09STom Joseph         sockAttrIface = server.add_interface(objPath, sockAttrIntfName);
43983241c09STom Joseph         sockAttrIface->register_property(
44083241c09STom Joseph             sockAttrPropPort, portNum,
44190f2da3fSRichard Marian Thomaiyar             [this](const uint16_t& req, uint16_t& 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)
44990f2da3fSRichard Marian Thomaiyar                     {
45090f2da3fSRichard Marian Thomaiyar                         return 0;
45190f2da3fSRichard Marian Thomaiyar                     }
4520084047dSAppaRao Puli                     portNum = req;
45390f2da3fSRichard Marian Thomaiyar                     updatedFlag |=
45490f2da3fSRichard Marian Thomaiyar                         (1 << static_cast<uint8_t>(UpdatedProp::port));
4550084047dSAppaRao Puli                     startServiceRestartTimer();
45690f2da3fSRichard Marian Thomaiyar                 }
45790f2da3fSRichard Marian Thomaiyar                 res = req;
45890f2da3fSRichard Marian Thomaiyar                 return 1;
45990f2da3fSRichard Marian Thomaiyar             });
46090f2da3fSRichard Marian Thomaiyar     }
46190f2da3fSRichard Marian Thomaiyar 
46283241c09STom Joseph     srvCfgIface->register_property(
46390f2da3fSRichard Marian Thomaiyar         srvCfgPropMasked, unitMaskedState, [this](const bool& req, bool& res) {
46490f2da3fSRichard Marian Thomaiyar             if (!internalSet)
46590f2da3fSRichard Marian Thomaiyar             {
46690f2da3fSRichard Marian Thomaiyar                 if (req == res)
46790f2da3fSRichard Marian Thomaiyar                 {
46890f2da3fSRichard Marian Thomaiyar                     return 1;
46990f2da3fSRichard Marian Thomaiyar                 }
47090f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
47190f2da3fSRichard Marian Thomaiyar                 {
47290f2da3fSRichard Marian Thomaiyar                     return 0;
47390f2da3fSRichard Marian Thomaiyar                 }
47490f2da3fSRichard Marian Thomaiyar                 unitMaskedState = req;
47590f2da3fSRichard Marian Thomaiyar                 unitEnabledState = !unitMaskedState;
47690f2da3fSRichard Marian Thomaiyar                 unitRunningState = !unitMaskedState;
47790f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
47890f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::maskedState)) |
47990f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState)) |
48090f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
48190f2da3fSRichard Marian Thomaiyar                 internalSet = true;
48283241c09STom Joseph                 srvCfgIface->set_property(srvCfgPropEnabled, unitEnabledState);
48383241c09STom Joseph                 srvCfgIface->set_property(srvCfgPropRunning, unitRunningState);
48490f2da3fSRichard Marian Thomaiyar                 internalSet = false;
48590f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
48690f2da3fSRichard Marian Thomaiyar             }
4870084047dSAppaRao Puli             res = req;
4880084047dSAppaRao Puli             return 1;
4890084047dSAppaRao Puli         });
4900084047dSAppaRao Puli 
49183241c09STom Joseph     srvCfgIface->register_property(
49290f2da3fSRichard Marian Thomaiyar         srvCfgPropEnabled, unitEnabledState,
49390f2da3fSRichard Marian Thomaiyar         [this](const bool& req, bool& res) {
49490f2da3fSRichard Marian Thomaiyar             if (!internalSet)
49590f2da3fSRichard Marian Thomaiyar             {
4960084047dSAppaRao Puli                 if (req == res)
4970084047dSAppaRao Puli                 {
4980084047dSAppaRao Puli                     return 1;
4990084047dSAppaRao Puli                 }
50090f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
5010084047dSAppaRao Puli                 {
50290f2da3fSRichard Marian Thomaiyar                     return 0;
5030084047dSAppaRao Puli                 }
50490f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
50590f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
5060084047dSAppaRao Puli                     phosphor::logging::log<phosphor::logging::level::ERR>(
5070084047dSAppaRao Puli                         "Invalid value specified");
5080084047dSAppaRao Puli                     return -EINVAL;
5090084047dSAppaRao Puli                 }
51090f2da3fSRichard Marian Thomaiyar                 unitEnabledState = req;
51190f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
51290f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::enabledState));
5130084047dSAppaRao Puli                 startServiceRestartTimer();
51490f2da3fSRichard Marian Thomaiyar             }
51590f2da3fSRichard Marian Thomaiyar             res = req;
51690f2da3fSRichard Marian Thomaiyar             return 1;
51790f2da3fSRichard Marian Thomaiyar         });
51890f2da3fSRichard Marian Thomaiyar 
51983241c09STom Joseph     srvCfgIface->register_property(
52090f2da3fSRichard Marian Thomaiyar         srvCfgPropRunning, unitRunningState,
52190f2da3fSRichard Marian Thomaiyar         [this](const bool& req, bool& res) {
52290f2da3fSRichard Marian Thomaiyar             if (!internalSet)
52390f2da3fSRichard Marian Thomaiyar             {
52490f2da3fSRichard Marian Thomaiyar                 if (req == res)
52590f2da3fSRichard Marian Thomaiyar                 {
52690f2da3fSRichard Marian Thomaiyar                     return 1;
52790f2da3fSRichard Marian Thomaiyar                 }
52890f2da3fSRichard Marian Thomaiyar                 if (updateInProgress)
52990f2da3fSRichard Marian Thomaiyar                 {
53090f2da3fSRichard Marian Thomaiyar                     return 0;
53190f2da3fSRichard Marian Thomaiyar                 }
53290f2da3fSRichard Marian Thomaiyar                 if (unitMaskedState)
53390f2da3fSRichard Marian Thomaiyar                 { // block updating if masked
53490f2da3fSRichard Marian Thomaiyar                     phosphor::logging::log<phosphor::logging::level::ERR>(
53590f2da3fSRichard Marian Thomaiyar                         "Invalid value specified");
53690f2da3fSRichard Marian Thomaiyar                     return -EINVAL;
53790f2da3fSRichard Marian Thomaiyar                 }
53890f2da3fSRichard Marian Thomaiyar                 unitRunningState = req;
53990f2da3fSRichard Marian Thomaiyar                 updatedFlag |=
54090f2da3fSRichard Marian Thomaiyar                     (1 << static_cast<uint8_t>(UpdatedProp::runningState));
54190f2da3fSRichard Marian Thomaiyar                 startServiceRestartTimer();
54290f2da3fSRichard Marian Thomaiyar             }
5430084047dSAppaRao Puli             res = req;
5440084047dSAppaRao Puli             return 1;
5450084047dSAppaRao Puli         });
5460084047dSAppaRao Puli 
54783241c09STom Joseph     srvCfgIface->initialize();
54883241c09STom Joseph     if (!socketObjectPath.empty())
54983241c09STom Joseph     {
55083241c09STom Joseph         sockAttrIface->initialize();
55183241c09STom Joseph     }
5520084047dSAppaRao Puli     return;
5530084047dSAppaRao Puli }
5540084047dSAppaRao Puli 
5550084047dSAppaRao Puli } // namespace service
5560084047dSAppaRao Puli } // namespace phosphor
557