Add methods for masking and unmasking service 25/30725/2
authorLukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Mon, 24 Nov 2014 05:30:20 +0000 (06:30 +0100)
committerLukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Mon, 24 Nov 2014 17:16:05 +0000 (18:16 +0100)
Masking a service prevents the service from being started.
Unmasking allows to start service again. Both of these operations
are implemented to affect service only till device reboot.
Masking and unmasking service needs reloading configuration
of dbus manager. That is also done in implementation.

Change-Id: Ibbb64dbae6ed6aaa68b085f8a66d4810cecd22c1

tests/common/dbus_access.cpp
tests/common/dbus_access.h

index e83ed52..7d0390f 100644 (file)
@@ -43,6 +43,7 @@ DBusAccess::DBusAccess(const char *service_name)
   , m_dbus_systemd_manager_interface("org.freedesktop.systemd1.Manager")
   , m_dbus_systemd_properties_interface("org.freedesktop.DBus.Properties")
   , m_dbus_systemd_service_interface("org.freedesktop.systemd1.Service")
+  , m_reloadingToken("Reloading")
 {
     dbus_error_init(&m_err);
     connectToDBus();
@@ -75,6 +76,14 @@ void DBusAccess::subscribeSignals() {
     finalizeMsgReply();
 }
 
+void DBusAccess::reloadDbusManager() {
+    newMethodCall("Reload");
+    sendMsgWithReply();
+    getMsgReply();
+    finalizeMsgReply();
+    m_runningJobs.insert(m_reloadingToken);
+}
+
 void DBusAccess::requestName() {
     dbus_bus_request_name(m_conn, m_dbus_client_name.c_str(),
         DBUS_NAME_FLAG_REPLACE_EXISTING , &m_err);
@@ -109,6 +118,37 @@ void DBusAccess::appendToMsg(const char *argument) {
         "Error in dbus_message_iter_append_basic");
 }
 
+void DBusAccess::appendToMsg(const char *const *argument) {
+    DBusMessageIter iter;
+    DBusMessageIter subIter;
+    int ret;
+
+    dbus_message_iter_init_append(m_msg, &iter);
+    ret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
+                                           &subIter);
+    RUNNER_ASSERT_MSG(ret != 0,
+        "Error in dbus_message_iter_open_container");
+    for (auto str = argument; *str; str++) {
+        int ret = dbus_message_iter_append_basic(&subIter, DBUS_TYPE_STRING, str);
+        RUNNER_ASSERT_MSG(ret != 0,
+            "Error in dbus_message_iter_append_basic");
+    }
+    ret = dbus_message_iter_close_container(&iter, &subIter);
+    RUNNER_ASSERT_MSG(ret != 0,
+        "Error in dbus_message_iter_close_container");
+}
+
+void DBusAccess::appendToMsg(bool argument) {
+    DBusMessageIter iter;
+
+    dbus_message_iter_init_append(m_msg, &iter);
+    int b = argument ? 1 : 0;
+    int ret = dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN,
+        &b);
+    RUNNER_ASSERT_MSG(ret != 0,
+        "Error in dbus_message_iter_append_basic");
+}
+
 void DBusAccess::sendMsgWithReply() {
     int ret = dbus_connection_send_with_reply(m_conn, m_msg, &m_pending, -1);
     RUNNER_ASSERT_MSG(ret == 1,
@@ -177,6 +217,7 @@ void DBusAccess::connectToDBus() {
     connect();
     addBusMatch("JobRemoved");
     addBusMatch("JobNew");
+    addBusMatch("Reloading");
     dbus_connection_flush(m_conn);
     dbus_connection_add_filter(m_conn,
                                messageHandler,
@@ -196,6 +237,27 @@ void DBusAccess::sendToService(const char *method) {
     m_runningJobs.insert(handleObjectPathMsgReply());
 }
 
+void DBusAccess::sendMaskToService() {
+    const char *mask[] = {m_service_name.c_str(), nullptr};
+    newMethodCall("MaskUnitFiles");
+    appendToMsg(mask);
+    appendToMsg(true);
+    appendToMsg(true);
+    sendMsgWithReply();
+    getMsgReply();
+    finalizeMsgReply();
+}
+
+void DBusAccess::sendUnmaskToService() {
+    const char *mask[] = {m_service_name.c_str(), nullptr};
+    newMethodCall("UnmaskUnitFiles");
+    appendToMsg(mask);
+    appendToMsg(true);
+    sendMsgWithReply();
+    getMsgReply();
+    finalizeMsgReply();
+}
+
 uint32_t DBusAccess::getUIntProperty(const char *interface, const char *property)
 {
     m_msg = dbus_message_new_method_call(m_dbus_systemd_destination.c_str(),
@@ -226,6 +288,8 @@ DBusHandlerResult DBusAccess::messageHandler(DBusConnection *conn, DBusMessage *
         self->signalJobRemovedHandler(msg);
     else if (self->isSignal(msg, "JobNew"))
         self->signalJobNewHandler(msg);
+    else if (self->isSignal(msg, "Reloading"))
+        self->signalReloadingHandler(msg);
 
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
@@ -306,6 +370,23 @@ void DBusAccess::signalJobNewHandler(DBusMessage *msg) {
         m_runningJobs.insert(path);
 }
 
+void DBusAccess::signalReloadingHandler(DBusMessage *msg) {
+    DBusMessageIter iter;
+    RUNNER_ASSERT_MSG(dbus_message_iter_init(msg, &iter) != 0,
+        "Message has no arguments");
+
+    if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&iter)) {
+        RUNNER_FAIL_MSG("boolean type expected");
+    }
+    bool active;
+    dbus_message_iter_get_basic(&iter, &active);
+
+    if (active)
+        m_runningJobs.insert(m_reloadingToken);
+    else
+        m_runningJobs.erase(m_reloadingToken);
+}
+
 void DBusAccess::waitForRunningJobsFinish() {
     while (!m_runningJobs.empty())
         dbus_connection_read_write_dispatch(m_conn, -1);
@@ -333,6 +414,20 @@ pid_t DBusAccess::getServicePid() {
     return static_cast<pid_t>(getUIntProperty(m_dbus_systemd_service_interface.c_str(), "MainPID"));
 }
 
+void DBusAccess::maskService() {
+    sendMaskToService();
+    reloadDbusManager();
+    waitForRunningJobsFinish();
+    sendResetFailedToService();
+}
+
+void DBusAccess::unmaskService() {
+    sendUnmaskToService();
+    reloadDbusManager();
+    waitForRunningJobsFinish();
+    sendResetFailedToService();
+}
+
 DBusAccess::~DBusAccess() {
     dbus_connection_close(m_conn);
     if (m_conn)
index 597dc76..a3a62a2 100644 (file)
@@ -41,16 +41,21 @@ public:
     void stopService();
     void restartService();
     pid_t getServicePid();
+    void maskService();
+    void unmaskService();
 
     virtual ~DBusAccess();
 private:
     void connect();
     void addBusMatch(const char *member);
     void subscribeSignals();
+    void reloadDbusManager();
     void requestName();
     void getUnitPath();
     void newMethodCall(const char *method);
     void appendToMsg(const char *argument);
+    void appendToMsg(const char *const *argument);
+    void appendToMsg(bool argument);
     void sendMsgWithReply();
     void getMsgReply();
     std::string handleObjectPathMsgReply();
@@ -59,6 +64,8 @@ private:
 
     void connectToDBus();
     void sendToService(const char *method);
+    void sendMaskToService();
+    void sendUnmaskToService();
     uint32_t getUIntProperty(const char *interface, const char *property);
     void sendResetFailedToService();
 
@@ -66,6 +73,7 @@ private:
     bool isSignal(DBusMessage *msg, const char *signal);
     void signalJobRemovedHandler(DBusMessage *msg);
     void signalJobNewHandler(DBusMessage *msg);
+    void signalReloadingHandler(DBusMessage *msg);
     void waitForRunningJobsFinish();
 
     DBusConnection *m_conn;
@@ -84,6 +92,7 @@ private:
     const std::string m_dbus_systemd_service_interface;
 
     std::set<std::string> m_runningJobs;
+    const std::string m_reloadingToken;
 };
 
 #endif // _DBUS_ACCESS_H_