Improve socket-activated service handling
This patch provides a more generic way of handling socket-activated
services like dropbear. A socket-activated service only has base socket
unit and spawns service unit with instance name on incoming connection,
so the instanced units of it need to be ignored. And whether a service
is socket-activated can be determined by checking the existance of its
service object path.
Tested:
* Two socket-activated service, dropbear and obmc-console-ssh, can be
controlled as expected.
* Instances of socket-activated services are no loger added to monitor
list.
Change-Id: If8faa2248e5794a410f804125410608aa69b858d
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@intel.com>
diff --git a/inc/srvcfg_manager.hpp b/inc/srvcfg_manager.hpp
index f94e4ea..f70d6a0 100644
--- a/inc/srvcfg_manager.hpp
+++ b/inc/srvcfg_manager.hpp
@@ -99,8 +99,7 @@
bool unitEnabledState = false;
bool unitRunningState = false;
- // dropbear is handled specially because it is a socket-activated service.
- bool isDropBearService = false;
+ bool isSocketActivatedService = false;
std::string subStateValue;
bool isMaskedOut();
diff --git a/src/main.cpp b/src/main.cpp
index 3d67800..8e7a8a7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@
#include <filesystem>
#include <fstream>
+#include <unordered_map>
std::unique_ptr<boost::asio::steady_timer> timer = nullptr;
std::unique_ptr<boost::asio::steady_timer> initTimer = nullptr;
@@ -35,9 +36,11 @@
// Base service name list. All instance of these services and
// units(service/socket) will be managed by this daemon.
-static std::array<std::string, 6> serviceNames = {
- "phosphor-ipmi-net", "bmcweb", "phosphor-ipmi-kcs",
- "start-ipkvm", "obmc-console", "dropbear"};
+static std::unordered_map<std::string /* unitName */,
+ bool /* isSocketActivated */>
+ managedServices = {{"phosphor-ipmi-net", false}, {"bmcweb", false},
+ {"phosphor-ipmi-kcs", false}, {"start-ipkvm", false},
+ {"obmc-console", false}, {"dropbear", true}};
enum class UnitType
{
@@ -118,9 +121,14 @@
std::get<static_cast<int>(ListUnitElements::name)>(unit);
auto [unitName, type, instanceName] =
getUnitNameTypeAndInstance(fullUnitName);
- if (std::find(serviceNames.begin(), serviceNames.end(), unitName) !=
- serviceNames.end())
+ if (managedServices.count(unitName))
{
+ // For socket-activated units, ignore all its instances
+ if (managedServices.at(unitName) == true && !instanceName.empty())
+ {
+ continue;
+ }
+
std::string instantiatedUnitName =
unitName + addInstanceName(instanceName, "_40");
boost::replace_all(instantiatedUnitName, "-", "_2d");
diff --git a/src/srvcfg_manager.cpp b/src/srvcfg_manager.cpp
index 9840cc4..36857b8 100644
--- a/src/srvcfg_manager.cpp
+++ b/src/srvcfg_manager.cpp
@@ -231,7 +231,7 @@
void ServiceConfig::queryAndUpdateProperties()
{
std::string objectPath =
- isDropBearService ? socketObjectPath : serviceObjectPath;
+ isSocketActivatedService ? socketObjectPath : serviceObjectPath;
if (objectPath.empty())
{
return;
@@ -333,10 +333,7 @@
instanceName(instanceName_), serviceObjectPath(serviceObjPath_),
socketObjectPath(socketObjPath_)
{
- if (baseUnitName == "dropbear")
- {
- isDropBearService = true;
- }
+ isSocketActivatedService = serviceObjectPath.empty();
instantiatedUnitName = baseUnitName + addInstanceName(instanceName, "@");
updatedFlag = 0;
queryAndUpdateProperties();
@@ -375,15 +372,16 @@
{
systemdUnitAction(conn, yield, getSocketUnitName(), sysdStopUnit);
}
- if (!isDropBearService)
+ if (!isSocketActivatedService)
{
systemdUnitAction(conn, yield, getServiceUnitName(), sysdStopUnit);
}
else
{
- // Get the ListUnits property, find all the services of
- // `dropbear@<ip><port>.service` and stop the service through
- // the systemdUnitAction method
+ // For socket-activated service, each connection will spawn a
+ // service instance from template. Need to find all spawned service
+ // `<unitName>@<attribute>.service` and stop them through the
+ // systemdUnitAction method
boost::system::error_code ec;
auto listUnits =
conn->yield_method_call<std::vector<ListUnitsType>>(
@@ -400,7 +398,7 @@
const auto& status =
std::get<static_cast<int>(ListUnitElements::subState)>(
unit);
- if (service.find("dropbear@") != std::string::npos &&
+ if (service.find(baseUnitName + "@") != std::string::npos &&
service.find(".service") != std::string::npos &&
status == subStateRunning)
{
@@ -451,7 +449,7 @@
{
unitFiles = {getServiceUnitName()};
}
- else if (!socketObjectPath.empty() && isDropBearService)
+ else if (serviceObjectPath.empty())
{
unitFiles = {getSocketUnitName()};
}
@@ -479,7 +477,7 @@
systemdUnitAction(conn, yield, getSocketUnitName(),
sysdRestartUnit);
}
- if (!isDropBearService)
+ if (!serviceObjectPath.empty())
{
systemdUnitAction(conn, yield, getServiceUnitName(),
sysdRestartUnit);