blob: dcb96c98119f42929685c50cde4b6defb673f614 [file] [log] [blame]
Tomáš Peckaccd80c32020-06-22 14:44:32 +02001#include <sdbus-c++/sdbus-c++.h>
2#include "dbus_systemd_server.h"
3#include "utils/log-init.h"
4
5using namespace std::literals;
6
7namespace {
Tomáš Pecka74434252021-02-03 16:57:47 +01008static const std::string interfaceUnit = "org.freedesktop.systemd1.Unit";
9static const std::string interfaceManager = "org.freedesktop.systemd1.Manager";
10static const std::string objectPathManager = "/org/freedesktop/systemd1";
Tomáš Peckaccd80c32020-06-22 14:44:32 +020011}
12
13/** @brief Create a dbus server on the connection */
14DbusSystemdServer::DbusSystemdServer(sdbus::IConnection& connection)
15 : m_manager(sdbus::createObject(connection, objectPathManager))
16{
17 // create manager object
18 m_manager->registerMethod("Subscribe").onInterface(interfaceManager).implementedAs([] {}).withNoReply(); // no-op for us
19 m_manager->registerMethod("ListUnits").onInterface(interfaceManager).implementedAs([this]() { return ListUnits(); });
20 m_manager->registerSignal("UnitNew").onInterface(interfaceManager).withParameters<std::string, sdbus::ObjectPath>();
21 m_manager->finishRegistration();
22}
23
24/** @brief Creates a unit inside the test server. Registers dbus object and emits UnitNew signal. **/
Tomáš Peckaf2391d62020-11-06 14:02:00 +010025void DbusSystemdServer::createUnit(sdbus::IConnection& connection, const std::string& unitName, const sdbus::ObjectPath& objPath, const std::string& activeState, const std::string& subState)
Tomáš Peckaccd80c32020-06-22 14:44:32 +020026{
Tomáš Peckaf2391d62020-11-06 14:02:00 +010027 m_units.insert(std::make_pair(objPath, Unit(unitName, sdbus::createObject(connection, objPath), activeState, subState)));
Tomáš Peckaccd80c32020-06-22 14:44:32 +020028
29 Unit& unit = m_units.at(objPath);
30
31 unit.m_object->registerProperty("ActiveState").onInterface(interfaceUnit).withGetter([&unit]() {
32 return unit.m_activeState;
33 });
34 unit.m_object->registerProperty("SubState").onInterface(interfaceUnit).withGetter([&unit]() {
35 return unit.m_subState;
36 });
37 unit.m_object->finishRegistration();
38
39 m_manager->emitSignal("UnitNew").onInterface(interfaceManager).withArguments(std::string(objPath), objPath);
40}
41
42/**
43 * @brief Implementation of ListUnit method.
44 *
45 * The unit is represented as a (objectPath, activeState, subState) triplet only. Nothing more is required now.
46 * Therefore, the not interesting properties are unused.
47 * In real systemd, there are more properties (see ListUnits method in https://www.freedesktop.org/wiki/Software/systemd/dbus/)
48 */
49std::vector<DbusSystemdServer::UnitStruct> DbusSystemdServer::ListUnits()
50{
51 std::vector<UnitStruct> res;
52
Tomáš Peckaf2391d62020-11-06 14:02:00 +010053 for (const auto& [objPath, unit] : m_units) {
54 res.push_back(UnitStruct(unit.m_unitName, ""s, ""s, ""s, ""s, ""s, unit.m_object->getObjectPath(), 0, ""s, "/dummy"s));
Tomáš Peckaccd80c32020-06-22 14:44:32 +020055 }
56
57 return res;
58}
59
60/** @brief Changes unit state of the unit identified by object path (@p objPath) */
61void DbusSystemdServer::changeUnitState(const sdbus::ObjectPath& objPath, const std::string& activeState, const std::string& subState)
62{
63 if (auto it = m_units.find(objPath); it != m_units.end()) {
64 it->second.m_activeState = activeState;
65 it->second.m_subState = subState;
66 it->second.m_object->emitPropertiesChangedSignal(interfaceUnit, {"ActiveState", "SubState"});
67 }
68}
69
Tomáš Peckaf2391d62020-11-06 14:02:00 +010070DbusSystemdServer::Unit::Unit(std::string unitName, std::unique_ptr<sdbus::IObject> object, std::string activeState, std::string subState)
71 : m_unitName(std::move(unitName))
72 , m_object(std::move(object))
Tomáš Peckaccd80c32020-06-22 14:44:32 +020073 , m_activeState(std::move(activeState))
74 , m_subState(std::move(subState))
75{
Tomáš Peckaf2391d62020-11-06 14:02:00 +010076}