Added lock_domain/unlock_domain to container manager 11/31111/6
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 27 Nov 2014 14:05:36 +0000 (15:05 +0100)
committerJan Olszak <j.olszak@samsung.com>
Thu, 4 Dec 2014 09:58:41 +0000 (01:58 -0800)
[Feature]      Ability to lock/unlock domain
[Cause]        The need for the ability to lock/unlock domains
[Solution]     Add lock_domain/unlock_domain function
[Verification] Build, install, run

Change-Id: I169f94ceef462346a33530ec467c9bb239b57d85
Signed-off-by: Dariusz Michaluk <d.michaluk@samsung.com>
client/security-containers-client-impl.cpp
server/common-dbus-definitions.hpp
server/container.cpp
server/container.hpp
server/containers-manager.cpp
server/containers-manager.hpp
server/host-connection.cpp
server/host-connection.hpp
server/host-dbus-definitions.hpp
tests/unit_tests/client/ut-client.cpp
tests/unit_tests/server/ut-containers-manager.cpp

index b84e903..aa8a796 100644 (file)
@@ -472,16 +472,20 @@ VsmStatus Client::vsm_start_domain(const char*) noexcept
     return vsm_get_status();
 }
 
-VsmStatus Client::vsm_lock_domain(const char*) noexcept
+VsmStatus Client::vsm_lock_domain(const char* id) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
-    return vsm_get_status();
+    assert(id);
+
+    GVariant* args_in = g_variant_new("(s)", id);
+    return callMethod(HOST_INTERFACE, api::host::METHOD_LOCK_CONTAINER, args_in);
 }
 
-VsmStatus Client::vsm_unlock_domain(const char*) noexcept
+VsmStatus Client::vsm_unlock_domain(const char* id) noexcept
 {
-    mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented");
-    return vsm_get_status();
+    assert(id);
+
+    GVariant* args_in = g_variant_new("(s)", id);
+    return callMethod(HOST_INTERFACE, api::host::METHOD_UNLOCK_CONTAINER, args_in);
 }
 
 VsmStatus Client::vsm_add_state_callback(VsmContainerDbusStateCallback containerDbusStateCallback,
index 77d0949..389f73f 100644 (file)
 
 namespace security_containers {
 namespace api {
-const std::string ERROR_FORBIDDEN  = "org.tizen.containers.Error.Forbidden";
-const std::string ERROR_FORWARDED  = "org.tizen.containers.Error.Forwarded";
-const std::string ERROR_INVALID_ID = "org.tizen.containers.Error.InvalidId";
-const std::string ERROR_INTERNAL   = "org.tizen.containers.Error.Internal";
+const std::string ERROR_FORBIDDEN     = "org.tizen.containers.Error.Forbidden";
+const std::string ERROR_FORWARDED     = "org.tizen.containers.Error.Forwarded";
+const std::string ERROR_INVALID_ID    = "org.tizen.containers.Error.InvalidId";
+const std::string ERROR_INVALID_STATE = "org.tizen.containers.Error.InvalidState";
+const std::string ERROR_INTERNAL      = "org.tizen.containers.Error.Internal";
 
 const std::string METHOD_PROXY_CALL    = "ProxyCall";
 
index c371d8a..e1377d0 100644 (file)
@@ -258,6 +258,18 @@ bool Container::isStopped()
     return mAdmin->isStopped();
 }
 
+void Container::suspend()
+{
+    Lock lock(mReconnectMutex);
+    mAdmin->suspend();
+}
+
+void Container::resume()
+{
+    Lock lock(mReconnectMutex);
+    mAdmin->resume();
+}
+
 bool Container::isPaused()
 {
     Lock lock(mReconnectMutex);
index bc1303c..b0264cb 100644 (file)
@@ -154,6 +154,16 @@ public:
     bool isStopped();
 
     /**
+     * Suspend container.
+     */
+    void suspend();
+
+    /**
+     * Resume container.
+     */
+    void resume();
+
+    /**
      * @return Is the container in a paused state?
      */
     bool isPaused();
index d34cb87..c5fb04e 100644 (file)
@@ -116,6 +116,12 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet
     mHostConnection.setDestroyContainerCallback(bind(&ContainersManager::handleDestroyContainerCall,
                                                      this, _1, _2));
 
+    mHostConnection.setLockContainerCallback(bind(&ContainersManager::handleLockContainerCall,
+                                                  this, _1, _2));
+
+    mHostConnection.setUnlockContainerCallback(bind(&ContainersManager::handleUnlockContainerCall,
+                                                    this, _1, _2));
+
     for (auto& containerConfig : mConfig.containerConfigs) {
         createContainer(containerConfig);
     }
@@ -261,6 +267,27 @@ void ContainersManager::stopAll()
     }
 }
 
+bool ContainersManager::isPaused(const std::string& containerId)
+{
+    auto iter = mContainers.find(containerId);
+    if (iter == mContainers.end()) {
+        LOGE("No such container id: " << containerId);
+        throw ContainerOperationException("No such container");
+    }
+
+    return iter->second->isPaused();
+}
+
+bool ContainersManager::isRunning(const std::string& containerId)
+{
+    auto iter = mContainers.find(containerId);
+    if (iter == mContainers.end()) {
+        LOGE("No such container id: " << containerId);
+        throw ContainerOperationException("No such container");
+    }
+    return iter->second->isRunning();
+}
+
 std::string ContainersManager::getRunningForegroundContainerId()
 {
     for (auto& container : mContainers) {
@@ -774,4 +801,64 @@ void ContainersManager::handleDestroyContainerCall(const std::string& id,
     thread.detach(); //TODO fix it
 }
 
+void ContainersManager::handleLockContainerCall(const std::string& id,
+                                                dbus::MethodResultBuilder::Pointer result)
+{
+    LOGI("LockContainer call; Id=" << id );
+    auto iter = mContainers.find(id);
+    if (iter == mContainers.end()) {
+        LOGE("Failed to lock container - no such container id: " << id);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+        return;
+    }
+
+    auto& container = *iter->second;
+    if (!container.isRunning()) {
+        LOGE("Container id=" << id << " is not running.");
+        result->setError(api::ERROR_INVALID_STATE, "Container is not running");
+        return;
+    }
+
+    LOGT("Lock container");
+    try {
+        container.suspend();
+    } catch (ContainerOperationException& e) {
+        LOGE(e.what());
+        result->setError(api::ERROR_INTERNAL, e.what());
+        return;
+    }
+
+    result->setVoid();
+}
+
+void ContainersManager::handleUnlockContainerCall(const std::string& id,
+                                                  dbus::MethodResultBuilder::Pointer result)
+{
+    LOGI("UnlockContainer call; Id=" << id );
+    auto iter = mContainers.find(id);
+    if (iter == mContainers.end()) {
+        LOGE("Failed to unlock container - no such container id: " << id);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+        return;
+    }
+
+    auto& container = *iter->second;
+    if (!container.isPaused()) {
+        LOGE("Container id=" << id << " is not paused.");
+        result->setError(api::ERROR_INVALID_STATE, "Container is not paused");
+        return;
+    }
+
+    LOGT("Unlock container");
+    try {
+        container.resume();
+    } catch (ContainerOperationException& e) {
+        LOGE(e.what());
+        result->setError(api::ERROR_INTERNAL, e.what());
+        return;
+    }
+
+    result->setVoid();
+}
+
 } // namespace security_containers
index 4adaaf8..5f31b97 100644 (file)
@@ -79,6 +79,16 @@ public:
     void stopAll();
 
     /**
+     * @return Is the container in a paused state?
+     */
+    bool isPaused(const std::string& containerId);
+
+    /**
+     * @return Is the container running?
+     */
+    bool isRunning(const std::string& containerId);
+
+    /**
      * @return id of the currently focused/foreground container
      */
     std::string getRunningForegroundContainerId();
@@ -154,6 +164,10 @@ private:
                                    dbus::MethodResultBuilder::Pointer result);
     void handleDestroyContainerCall(const std::string& id,
                                     dbus::MethodResultBuilder::Pointer result);
+    void handleLockContainerCall(const std::string& id,
+                                 dbus::MethodResultBuilder::Pointer result);
+    void handleUnlockContainerCall(const std::string& id,
+                                   dbus::MethodResultBuilder::Pointer result);
 };
 
 
index 9b22f7b..f862b55 100644 (file)
@@ -160,6 +160,17 @@ void HostConnection::setDestroyContainerCallback(const DestroyContainerCallback&
     mDestroyContainerCallback = callback;
 }
 
+void HostConnection::setLockContainerCallback(const LockContainerCallback& callback)
+{
+    mLockContainerCallback = callback;
+}
+
+void HostConnection::setUnlockContainerCallback(const UnlockContainerCallback& callback)
+{
+    mUnlockContainerCallback = callback;
+}
+
+
 void HostConnection::onMessageCall(const std::string& objectPath,
                                         const std::string& interface,
                                         const std::string& methodName,
@@ -305,6 +316,24 @@ void HostConnection::onMessageCall(const std::string& objectPath,
             mDestroyContainerCallback(id, result);
         }
     }
+
+    if (methodName == api::host::METHOD_LOCK_CONTAINER) {
+        const gchar* id = NULL;
+        g_variant_get(parameters, "(&s)", &id);
+
+        if (mLockContainerCallback){
+            mLockContainerCallback(id, result);
+        }
+    }
+
+    if (methodName == api::host::METHOD_UNLOCK_CONTAINER) {
+        const gchar* id = NULL;
+        g_variant_get(parameters, "(&s)", &id);
+
+        if (mUnlockContainerCallback){
+            mUnlockContainerCallback(id, result);
+        }
+    }
 }
 
 void HostConnection::proxyCallAsync(const std::string& busName,
index ab13b50..0030efc 100644 (file)
@@ -89,6 +89,12 @@ public:
     typedef std::function<void(const std::string& id,
                                dbus::MethodResultBuilder::Pointer result
                               )> DestroyContainerCallback;
+    typedef std::function<void(const std::string& id,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> LockContainerCallback;
+    typedef std::function<void(const std::string& id,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> UnlockContainerCallback;
 
     /**
      * Register proxy call callback
@@ -151,6 +157,16 @@ public:
     void setDestroyContainerCallback(const DestroyContainerCallback& callback);
 
     /**
+     * Register a callback called to lock container
+     */
+    void setLockContainerCallback(const LockContainerCallback& callback);
+
+    /**
+     * Register a callback called to unlock container
+     */
+    void setUnlockContainerCallback(const UnlockContainerCallback& callback);
+
+    /**
      * Make a proxy call
      */
     void proxyCallAsync(const std::string& busName,
@@ -177,6 +193,8 @@ private:
     SetActiveContainerCallback mSetActiveContainerCallback;
     CreateContainerCallback mCreateContainerCallback;
     DestroyContainerCallback mDestroyContainerCallback;
+    LockContainerCallback mLockContainerCallback;
+    UnlockContainerCallback mUnlockContainerCallback;
 
     void onNameAcquired();
     void onNameLost();
index b61a4f8..1b134ea 100644 (file)
@@ -48,6 +48,8 @@ const std::string METHOD_DECLARE_LINK            = "DeclareLink";
 const std::string METHOD_SET_ACTIVE_CONTAINER    = "SetActiveContainer";
 const std::string METHOD_CREATE_CONTAINER        = "CreateContainer";
 const std::string METHOD_DESTROY_CONTAINER       = "DestroyContainer";
+const std::string METHOD_LOCK_CONTAINER          = "LockContainer";
+const std::string METHOD_UNLOCK_CONTAINER        = "UnlockContainer";
 
 const std::string SIGNAL_CONTAINER_DBUS_STATE    = "ContainerDbusState";
 
@@ -106,6 +108,12 @@ const std::string DEFINITION =
     "    <method name='" + METHOD_DESTROY_CONTAINER + "'>"
     "      <arg type='s' name='id' direction='in'/>"
     "    </method>"
+    "    <method name='" + METHOD_LOCK_CONTAINER + "'>"
+    "      <arg type='s' name='id' direction='in'/>"
+    "    </method>"
+    "    <method name='" + METHOD_UNLOCK_CONTAINER + "'>"
+    "      <arg type='s' name='id' direction='in'/>"
+    "    </method>"
     "    <signal name='" + SIGNAL_CONTAINER_DBUS_STATE + "'>"
     "      <arg type='s' name='container'/>"
     "      <arg type='s' name='dbusAddress'/>"
index 934a062..61ed580 100644 (file)
@@ -225,6 +225,20 @@ BOOST_AUTO_TEST_CASE(CreateContainerTest)
     vsm_client_free(client);
 }
 
+BOOST_AUTO_TEST_CASE(LockUnlockContainerTest)
+{
+    const std::string newActiveContainerId = "ut-containers-manager-console2-dbus";
+
+    VsmClient client = vsm_client_create();
+    VsmStatus status = vsm_connect(client);
+    BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
+    status = vsm_lock_domain(client, newActiveContainerId.c_str());
+    BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
+    status = vsm_unlock_domain(client, newActiveContainerId.c_str());
+    BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status);
+    vsm_client_free(client);
+}
+
 BOOST_AUTO_TEST_CASE(FileMoveRequestTest)
 {
     const std::string path = "/tmp/fake_path";
index ef990f7..73643a8 100644 (file)
@@ -408,6 +408,30 @@ public:
                                  asyncResult);
     }
 
+    void callMethodLockContainer(const std::string& id)
+    {
+        assert(isHost());
+        GVariant* parameters = g_variant_new("(s)", id.c_str());
+        GVariantPtr result = mClient->callMethod(api::host::BUS_NAME,
+                                                 api::host::OBJECT_PATH,
+                                                 api::host::INTERFACE,
+                                                 api::host::METHOD_LOCK_CONTAINER,
+                                                 parameters,
+                                                 "()");
+    }
+
+    void callMethodUnlockContainer(const std::string& id)
+    {
+        assert(isHost());
+        GVariant* parameters = g_variant_new("(s)", id.c_str());
+        GVariantPtr result = mClient->callMethod(api::host::BUS_NAME,
+                                                 api::host::OBJECT_PATH,
+                                                 api::host::INTERFACE,
+                                                 api::host::METHOD_UNLOCK_CONTAINER,
+                                                 parameters,
+                                                 "()");
+    }
+
 private:
     const int mId;
     DbusConnection::Pointer mClient;
@@ -1090,4 +1114,34 @@ BOOST_AUTO_TEST_CASE(DeclareLink)
                           expectedMessage("Not implemented"));
 }
 
+BOOST_AUTO_TEST_CASE(LockUnlockContainerTest)
+{
+    ContainersManager cm(TEST_DBUS_CONFIG_PATH);
+    cm.startAll();
+
+    DbusAccessory dbus(DbusAccessory::HOST_ID);
+
+    std::vector<std::string> containerIds = {"ut-containers-manager-console1-dbus",
+                                             "ut-containers-manager-console2-dbus",
+                                             "ut-containers-manager-console3-dbus"};
+
+    for (std::string& containerId: containerIds){
+        dbus.callMethodLockContainer(containerId);
+        BOOST_CHECK(cm.isPaused(containerId));
+        dbus.callMethodUnlockContainer(containerId);
+        BOOST_CHECK(cm.isRunning(containerId));
+    }
+
+    BOOST_REQUIRE_THROW(dbus.callMethodLockContainer(NON_EXISTANT_CONTAINER_ID),
+                        DbusException);
+    BOOST_REQUIRE_THROW(dbus.callMethodUnlockContainer(NON_EXISTANT_CONTAINER_ID),
+                        DbusException);
+
+    cm.stopAll();
+    BOOST_REQUIRE_THROW(dbus.callMethodLockContainer("ut-containers-manager-console1-dbus"),
+                        DbusException);
+    BOOST_REQUIRE_THROW(dbus.callMethodUnlockContainer("ut-containers-manager-console1-dbus"),
+                        DbusException);
+}
+
 BOOST_AUTO_TEST_SUITE_END()