Support for destroying container 66/30966/3
authorPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Thu, 27 Nov 2014 15:39:33 +0000 (16:39 +0100)
committerPiotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
Fri, 28 Nov 2014 13:30:01 +0000 (05:30 -0800)
[Bug/Feature]   N/A
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: I4303284b06fdebf452a040c9dfa2c1cddc0b8abf

22 files changed:
cli/command-line-interface.cpp
cli/command-line-interface.hpp
cli/main.cpp
client/security-containers-client-impl.cpp
client/security-containers-client.cpp
client/security-containers-client.h
server/common-dbus-definitions.hpp
server/container-admin.cpp
server/container-admin.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/configs/CMakeLists.txt
tests/unit_tests/server/configs/ut-containers-manager/empty-dbus-daemon.conf.in [new file with mode: 0644]
tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf [deleted file]
tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf.in [new file with mode: 0644]
tests/unit_tests/server/ut-containers-manager.cpp

index 0549afd..b46871d 100644 (file)
@@ -154,6 +154,17 @@ void create_domain(int pos, int argc, const char** argv)
     one_shot(bind(vsm_create_domain, _1, argv[pos + 1], nullptr));
 }
 
+void destroy_domain(int pos, int argc, const char** argv)
+{
+    using namespace std::placeholders;
+
+    if (argc <= pos + 1) {
+        throw runtime_error("Not enough parameters");
+    }
+
+    one_shot(bind(vsm_destroy_domain, _1, argv[pos + 1], 1));
+}
+
 void lock_domain(int pos, int argc, const char** argv)
 {
     using namespace std::placeholders;
index 41f5048..360f46c 100644 (file)
@@ -111,6 +111,13 @@ void set_active_container(int pos, int argc, const char** argv);
 void create_domain(int pos, int argc, const char** argv);
 
 /**
+ * Parses command line arguments and call vsm_destroy_domain
+ *
+ * @see vsm_destroy_domain
+ */
+void destroy_domain(int pos, int argc, const char** argv);
+
+/**
  * Parses command line arguments and call vsm_lock_domain
  *
  * @see vsm_lock_domain
index 774881b..0ceb1e5 100644 (file)
@@ -50,6 +50,14 @@ std::map<std::string, CommandLineInterface> commands = {
         }
     },
     {
+        "destroy_domain", {
+            destroy_domain,
+            "destroy_domain container_id",
+            "Destroy container",
+            {{"container_id", "id container name"}}
+        }
+    },
+    {
         "lock_domain", {
             lock_domain,
             "lock_domain container_id",
index 0f08a02..1a6e999 100644 (file)
@@ -450,13 +450,14 @@ VsmStatus Client::vsm_create_domain(const char* id, const char* tname) noexcept
     }
 
     GVariant* args_in = g_variant_new("(s)", id);
-    return callMethod(HOST_INTERFACE, api::host::METHOD_ADD_CONTAINER, args_in);
+    return callMethod(HOST_INTERFACE, api::host::METHOD_CREATE_CONTAINER, args_in);
 }
 
-VsmStatus Client::vsm_destroy_domain(const char*) noexcept
+VsmStatus Client::vsm_destroy_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_DESTROY_CONTAINER, args_in);
 }
 
 VsmStatus Client::vsm_shutdown_domain(const char*) noexcept
index b96718f..ef571c8 100644 (file)
@@ -158,7 +158,7 @@ API VsmStatus vsm_create_domain(VsmClient client, const char* id, const char* tn
     return getClient(client).vsm_create_domain(id, tname);
 }
 
-API VsmStatus vsm_destroy_domain(VsmClient client, const char* id)
+API VsmStatus vsm_destroy_domain(VsmClient client, const char* id, int /*force*/)
 {
     return getClient(client).vsm_destroy_domain(id);
 }
index b796c16..e7e738c 100644 (file)
@@ -380,7 +380,7 @@ VsmStatus vsm_create_domain(VsmClient client, const char* id, const char* tname)
  * @param[in] force if 0 data will be kept, otherwise data will be lost
  * @return status of this function call
  */
-VsmStatus vsm_destroy_domain(VsmStatus clent, const char* id, int force);
+VsmStatus vsm_destroy_domain(VsmClient clent, const char* id, int force);
 
 /**
  * Shutdown domain
index 14bb037..77d0949 100644 (file)
@@ -32,7 +32,7 @@ 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_UNKNOWN_ID = "org.tizen.containers.Error.UnknownId";
+const std::string ERROR_INVALID_ID = "org.tizen.containers.Error.InvalidId";
 const std::string ERROR_INTERNAL   = "org.tizen.containers.Error.Internal";
 
 const std::string METHOD_PROXY_CALL    = "ProxyCall";
index ef8ae0f..65179c3 100644 (file)
@@ -111,6 +111,15 @@ ContainerAdmin::~ContainerAdmin()
 {
     LOGD(mId << ": Destroying ContainerAdmin object...");
 
+    if (mDestroyOnExit) {
+        if (!mDom.stop()) {
+            LOGE(mId << ": Failed to stop the container");
+        }
+        if (!mDom.destroy()) {
+            LOGE(mId << ": Failed to destroy the container");
+        }
+    }
+
     if (!mDetachOnExit) {
         // Try to forcefully stop
         if (!mDom.stop()) {
@@ -271,6 +280,11 @@ void ContainerAdmin::setDetachOnExit()
     mDetachOnExit = true;
 }
 
+void ContainerAdmin::setDestroyOnExit()
+{
+    mDestroyOnExit = true;
+}
+
 std::int64_t ContainerAdmin::getSchedulerQuota()
 {
 //    assert(mDom);
index 79b0193..f3c9a4f 100644 (file)
@@ -116,6 +116,11 @@ public:
     void setDetachOnExit();
 
     /**
+     * Set if container should be destroyed on exit.
+     */
+    void setDestroyOnExit();
+
+    /**
      * @return Scheduler CFS quota,
      * TODO: this function is only for UNIT TESTS
      */
@@ -126,6 +131,7 @@ private:
     lxc::LxcDomain mDom;
     const std::string mId;
     bool mDetachOnExit;
+    bool mDestroyOnExit;
 
     void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota);
 };
index 80decd5..c371d8a 100644 (file)
@@ -240,6 +240,12 @@ void Container::setDetachOnExit()
     }
 }
 
+void Container::setDestroyOnExit()
+{
+    Lock lock(mReconnectMutex);
+    mAdmin->setDestroyOnExit();
+}
+
 bool Container::isRunning()
 {
     Lock lock(mReconnectMutex);
index 76e098a..bc1303c 100644 (file)
@@ -135,6 +135,11 @@ public:
     void setDetachOnExit();
 
     /**
+     * Set if container should be destroyed on exit.
+     */
+    void setDestroyOnExit();
+
+    /**
      * @return Is the container running?
      */
     bool isRunning();
index def04c2..5a6a32b 100644 (file)
@@ -101,11 +101,14 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet
     mHostConnection.setSetActiveContainerCallback(bind(&ContainersManager::handleSetActiveContainerCall,
                                                        this, _1, _2));
 
-    mHostConnection.setAddContainerCallback(bind(&ContainersManager::handleAddContainerCall,
-                                                           this, _1, _2));
+    mHostConnection.setCreateContainerCallback(bind(&ContainersManager::handleCreateContainerCall,
+                                                    this, _1, _2));
+
+    mHostConnection.setDestroyContainerCallback(bind(&ContainersManager::handleDestroyContainerCall,
+                                                     this, _1, _2));
 
     for (auto& containerConfig : mConfig.containerConfigs) {
-        addContainer(containerConfig);
+        createContainer(containerConfig);
     }
 
     // check if default container exists, throw ContainerOperationException if not found
@@ -143,7 +146,7 @@ ContainersManager::~ContainersManager()
     LOGD("ContainersManager object destroyed");
 }
 
-void ContainersManager::addContainer(const std::string& containerConfig)
+void ContainersManager::createContainer(const std::string& containerConfig)
 {
     std::string baseConfigPath = utils::dirName(mConfigPath);
     std::string containerConfigPath = utils::getAbsolutePath(containerConfig, baseConfigPath);
@@ -177,6 +180,20 @@ void ContainersManager::addContainer(const std::string& containerConfig)
     mContainers.insert(ContainerMap::value_type(id, std::move(c)));
 }
 
+void ContainersManager::destroyContainer(const std::string& containerId)
+{
+    // TODO mutex for mContainers access
+    auto it = mContainers.find(containerId);
+    if (it == mContainers.end()) {
+        LOGE("Failed to destroy container " << containerId << ": no such container");
+        throw ContainerOperationException("No such container");
+    }
+
+    // TODO give back the focus
+    it->second->setDestroyOnExit();
+    mContainers.erase(it);
+}
+
 void ContainersManager::focus(const std::string& containerId)
 {
     /* try to access the object first to throw immediately if it doesn't exist */
@@ -440,7 +457,7 @@ void ContainersManager::handleProxyCall(const std::string& caller,
     ContainerMap::const_iterator targetIter = mContainers.find(target);
     if (targetIter == mContainers.end()) {
         LOGE("Target container '" << target << "' not found");
-        result->setError(api::ERROR_UNKNOWN_ID, "Unknown proxy call target");
+        result->setError(api::ERROR_INVALID_ID, "Unknown proxy call target");
         return;
     }
 
@@ -501,7 +518,7 @@ void ContainersManager::handleGetContainerInfoCall(const std::string& id,
     LOGI("GetContainerInfo call");
     if (mContainers.count(id) == 0) {
         LOGE("No container with id=" << id);
-        result->setError(api::ERROR_UNKNOWN_ID, "No such container id");
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
         return;
     }
     const auto& container = mContainers[id];
@@ -536,7 +553,7 @@ void ContainersManager::handleSetActiveContainerCall(const std::string& id,
     auto container = mContainers.find(id);
     if (container == mContainers.end()){
         LOGE("No container with id=" << id );
-        result->setError(api::ERROR_UNKNOWN_ID, "No such container id");
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
         return;
     }
 
@@ -597,33 +614,30 @@ void ContainersManager::generateNewConfig(const std::string& id,
                                 fs::perms::others_read);
 }
 
-void ContainersManager::handleAddContainerCall(const std::string& id,
-                                               dbus::MethodResultBuilder::Pointer result)
+void ContainersManager::handleCreateContainerCall(const std::string& id,
+                                                  dbus::MethodResultBuilder::Pointer result)
 {
     if (id.empty()) {
         LOGE("Failed to add container - invalid name.");
-        result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
-                         "Failed to add container - invalid name.");
+        result->setError(api::ERROR_INVALID_ID, "Invalid name");
         return;
     }
 
-    LOGI("Adding container " << id);
+    LOGI("Creating container " << id);
 
     // TODO: This solution is temporary. It utilizes direct access to config files when creating new
     // containers. Update this handler when config database will appear.
     namespace fs = boost::filesystem;
 
-    boost::system::error_code ec;
-    const std::string containerPathStr = utils::createFilePath(mConfig.containersPath, "/", id, "/");
-
     // check if container does not exist
     if (mContainers.find(id) != mContainers.end()) {
         LOGE("Cannot create " << id << " container - already exists!");
-        result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
-                         "Cannot create " + id + " container - already exists!");
+        result->setError(api::ERROR_INVALID_ID, "Already exists");
         return;
     }
 
+    const std::string containerPathStr = utils::createFilePath(mConfig.containersPath, "/", id, "/");
+
     // copy container image if config contains path to image
     LOGT("Image path: " << mConfig.containerImagePath);
     if (!mConfig.containerImagePath.empty()) {
@@ -633,8 +647,7 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
 
         if (!utils::launchAsRoot(copyImageContentsWrapper)) {
             LOGE("Failed to copy container image.");
-            result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
-                            "Failed to copy container image.");
+            result->setError(api::ERROR_INTERNAL, "Failed to copy container image.");
             return;
         }
     }
@@ -647,7 +660,7 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
     std::string configPath = utils::createFilePath(templateDir, "/", CONTAINER_TEMPLATE_CONFIG_PATH);
     std::string newConfigPath = utils::createFilePath(configDir, "/containers/", id + ".conf");
 
-    auto removeAllWrapper = [](const std::string& path) {
+    auto removeAllWrapper = [](const std::string& path) -> bool {
         try {
             LOGD("Removing copied data");
             fs::remove_all(fs::path(path));
@@ -662,19 +675,19 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
         generateNewConfig(id, configPath, newConfigPath);
 
     } catch (SecurityContainersException& e) {
-        LOGE(e.what());
+        LOGE("Generate config failed: " << e.what());
         utils::launchAsRoot(std::bind(removeAllWrapper, containerPathStr));
-        result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED, e.what());
+        result->setError(api::ERROR_INTERNAL, "Failed to generate config");
         return;
     }
 
-    LOGT("Adding new container");
+    LOGT("Creating new container");
     try {
-        addContainer(newConfigPath);
+        createContainer(newConfigPath);
     } catch (SecurityContainersException& e) {
-        LOGE(e.what());
+        LOGE("Creating new container failed: " << e.what());
         utils::launchAsRoot(std::bind(removeAllWrapper, containerPathStr));
-        result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED, e.what());
+        result->setError(api::ERROR_INTERNAL, "Failed to create container");
         return;
     }
 
@@ -685,11 +698,36 @@ void ContainersManager::handleAddContainerCall(const std::string& id,
         } else {
             LOGE("Failed to start container.");
             // TODO removeContainer
-            result->setError(api::host::ERROR_CONTAINER_CREATE_FAILED,
-                             "Failed to start container.");
+            result->setError(api::ERROR_INTERNAL, "Failed to start container");
         }
     };
     mContainers[id]->startAsync(resultCallback);
 }
 
+void ContainersManager::handleDestroyContainerCall(const std::string& id,
+                                                   dbus::MethodResultBuilder::Pointer result)
+{
+    if (mContainers.find(id) == mContainers.end()) {
+        LOGE("Failed to destroy container - no such container id: " << id);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+        return;
+    }
+
+    LOGI("Destroying container " << id);
+
+    auto destroyer = [id, result, this] {
+        try {
+            destroyContainer(id);
+        } catch (const SecurityContainersException& e) {
+            LOGE("Error during container destruction: " << e.what());
+            result->setError(api::ERROR_INTERNAL, "Failed to destroy container");
+            return;
+        }
+        result->setVoid();
+    };
+
+    std::thread thread(destroyer);
+    thread.detach(); //TODO fix it
+}
+
 } // namespace security_containers
index 16a8cf5..70637bc 100644 (file)
@@ -47,11 +47,18 @@ public:
     ~ContainersManager();
 
     /**
-     * Add new container.
+     * Create new container.
      *
      * @param containerConfig config of new container
      */
-    void addContainer(const std::string& containerConfig);
+    void createContainer(const std::string& containerConfig);
+
+    /**
+     * Destroy container.
+     *
+     * @param containerId id of the container
+     */
+    void destroyContainer(const std::string& containerId);
 
     /**
      * Focus this container, put it to the foreground.
@@ -126,8 +133,10 @@ private:
     void handleGetContainerInfoCall(const std::string& id, dbus::MethodResultBuilder::Pointer result);
     void handleSetActiveContainerCall(const std::string& id,
                                       dbus::MethodResultBuilder::Pointer result);
-    void handleAddContainerCall(const std::string& id,
-                                          dbus::MethodResultBuilder::Pointer result);
+    void handleCreateContainerCall(const std::string& id,
+                                   dbus::MethodResultBuilder::Pointer result);
+    void handleDestroyContainerCall(const std::string& id,
+                                    dbus::MethodResultBuilder::Pointer result);
 };
 
 
index 1b38a9c..b7d72b7 100644 (file)
@@ -135,9 +135,14 @@ void HostConnection::setSetActiveContainerCallback(const SetActiveContainerCallb
     mSetActiveContainerCallback = callback;
 }
 
-void HostConnection::setAddContainerCallback(const AddContainerCallback& callback)
+void HostConnection::setCreateContainerCallback(const CreateContainerCallback& callback)
 {
-    mAddContainerCallback = callback;
+    mCreateContainerCallback = callback;
+}
+
+void HostConnection::setDestroyContainerCallback(const DestroyContainerCallback& callback)
+{
+    mDestroyContainerCallback = callback;
 }
 
 void HostConnection::onMessageCall(const std::string& objectPath,
@@ -220,12 +225,21 @@ void HostConnection::onMessageCall(const std::string& objectPath,
         return;
     }
 
-    if (methodName == api::host::METHOD_ADD_CONTAINER) {
+    if (methodName == api::host::METHOD_CREATE_CONTAINER) {
+        const gchar* id = NULL;
+        g_variant_get(parameters, "(&s)", &id);
+
+        if (mCreateContainerCallback){
+            mCreateContainerCallback(id, result);
+        }
+    }
+
+    if (methodName == api::host::METHOD_DESTROY_CONTAINER) {
         const gchar* id = NULL;
         g_variant_get(parameters, "(&s)", &id);
 
-        if (mAddContainerCallback){
-            mAddContainerCallback(id, result);
+        if (mDestroyContainerCallback){
+            mDestroyContainerCallback(id, result);
         }
     }
 }
index 1dacd11..8392578 100644 (file)
@@ -65,7 +65,10 @@ public:
                               )> SetActiveContainerCallback;
     typedef std::function<void(const std::string& id,
                                dbus::MethodResultBuilder::Pointer result
-                              )> AddContainerCallback;
+                              )> CreateContainerCallback;
+    typedef std::function<void(const std::string& id,
+                               dbus::MethodResultBuilder::Pointer result
+                              )> DestroyContainerCallback;
 
     /**
      * Register proxy call callback
@@ -105,7 +108,12 @@ public:
     /**
      * Register a callback called to create new container
      */
-    void setAddContainerCallback(const AddContainerCallback& callback);
+    void setCreateContainerCallback(const CreateContainerCallback& callback);
+
+    /**
+     * Register a callback called to destroy container
+     */
+    void setDestroyContainerCallback(const DestroyContainerCallback& callback);
 
     /**
      * Make a proxy call
@@ -129,7 +137,8 @@ private:
     GetActiveContainerIdCallback mGetActiveContainerIdCallback;
     GetContainerInfoCallback mGetContainerInfoCallback;
     SetActiveContainerCallback mSetActiveContainerCallback;
-    AddContainerCallback mAddContainerCallback;
+    CreateContainerCallback mCreateContainerCallback;
+    DestroyContainerCallback mDestroyContainerCallback;
 
     void onNameAcquired();
     void onNameLost();
index a722aee..b7b49c4 100644 (file)
@@ -37,14 +37,14 @@ const std::string OBJECT_PATH                    = "/org/tizen/containers/host";
 const std::string INTERFACE                      = "org.tizen.containers.host.manager";
 
 const std::string ERROR_CONTAINER_STOPPED        = "org.tizen.containers.host.Error.ContainersStopped";
-const std::string ERROR_CONTAINER_CREATE_FAILED  = "org.tizen.containers.host.Error.ContainerCreateFailed";
 
 const std::string METHOD_GET_CONTAINER_DBUSES    = "GetContainerDbuses";
 const std::string METHOD_GET_CONTAINER_ID_LIST   = "GetContainerIds";
 const std::string METHOD_GET_ACTIVE_CONTAINER_ID = "GetActiveContainerId";
 const std::string METHOD_GET_CONTAINER_INFO      = "GetContainerInfo";
 const std::string METHOD_SET_ACTIVE_CONTAINER    = "SetActiveContainer";
-const std::string METHOD_ADD_CONTAINER           = "AddContainer";
+const std::string METHOD_CREATE_CONTAINER        = "CreateContainer";
+const std::string METHOD_DESTROY_CONTAINER       = "DestroyContainer";
 
 const std::string SIGNAL_CONTAINER_DBUS_STATE    = "ContainerDbusState";
 
@@ -77,7 +77,10 @@ const std::string DEFINITION =
     "    <method name='" + METHOD_SET_ACTIVE_CONTAINER + "'>"
     "      <arg type='s' name='id' direction='in'/>"
     "    </method>"
-    "    <method name='" + METHOD_ADD_CONTAINER + "'>"
+    "    <method name='" + METHOD_CREATE_CONTAINER + "'>"
+    "      <arg type='s' name='id' direction='in'/>"
+    "    </method>"
+    "    <method name='" + METHOD_DESTROY_CONTAINER + "'>"
     "      <arg type='s' name='id' direction='in'/>"
     "    </method>"
     "    <signal name='" + SIGNAL_CONTAINER_DBUS_STATE + "'>"
index d6b3fbb..934a062 100644 (file)
@@ -213,7 +213,7 @@ BOOST_AUTO_TEST_CASE(SetActiveContainerTest)
     vsm_client_free(client);
 }
 
-BOOST_AUTO_TEST_CASE(AddContainerTest)
+BOOST_AUTO_TEST_CASE(CreateContainerTest)
 {
     const std::string newActiveContainerId = "";
 
index 17e10a2..fc73fd4 100644 (file)
@@ -24,7 +24,6 @@ FILE(GLOB server_container_CONF     ut-server/containers/*.conf)
 
 FILE(GLOB manager_manager_CONF      ut-containers-manager/*.conf)
 FILE(GLOB manager_container_CONF    ut-containers-manager/containers/*.conf)
-FILE(GLOB manager_admin_TEMPLATE    ut-containers-manager/templates/*.conf)
 
 FILE(GLOB container_CONF            ut-container/*.conf)
 FILE(GLOB container_container_CONF  ut-container/containers/*.conf)
@@ -55,6 +54,8 @@ CONFIGURE_FILE(ut-containers-manager/buggy-foreground-daemon.conf.in
                ${CMAKE_BINARY_DIR}/ut-containers-manager/buggy-foreground-daemon.conf @ONLY)
 CONFIGURE_FILE(ut-containers-manager/test-dbus-daemon.conf.in
                ${CMAKE_BINARY_DIR}/ut-containers-manager/test-dbus-daemon.conf @ONLY)
+CONFIGURE_FILE(ut-containers-manager/empty-dbus-daemon.conf.in
+               ${CMAKE_BINARY_DIR}/ut-containers-manager/empty-dbus-daemon.conf @ONLY)
 FILE(GLOB manager_manager_CONF_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/*.conf)
 
 CONFIGURE_FILE(ut-containers-manager/containers/console1-dbus.conf.in
@@ -65,6 +66,10 @@ CONFIGURE_FILE(ut-containers-manager/containers/console3-dbus.conf.in
                ${CMAKE_BINARY_DIR}/ut-containers-manager/containers/console3-dbus.conf @ONLY)
 FILE(GLOB manager_container_CONF_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/containers/*.conf)
 
+CONFIGURE_FILE(ut-containers-manager/templates/template.conf.in
+               ${CMAKE_BINARY_DIR}/ut-containers-manager/templates/template.conf @ONLY)
+FILE(GLOB manager_container_TEMPLATE_GEN ${CMAKE_BINARY_DIR}/ut-containers-manager/templates/*.conf)
+
 
 ## Install #####################################################################
 INSTALL(FILES        ${server_manager_CONF}
@@ -82,7 +87,7 @@ INSTALL(FILES        ${manager_container_CONF}
         DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/containers)
 INSTALL(FILES        ${manager_container_CONF_GEN}
         DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/containers)
-INSTALL(FILES        ${manager_admin_TEMPLATE}
+INSTALL(FILES        ${manager_container_TEMPLATE_GEN}
         DESTINATION  ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-containers-manager/templates)
 
 INSTALL(FILES        ${container_CONF}
diff --git a/tests/unit_tests/server/configs/ut-containers-manager/empty-dbus-daemon.conf.in b/tests/unit_tests/server/configs/ut-containers-manager/empty-dbus-daemon.conf.in
new file mode 100644 (file)
index 0000000..82f6c0e
--- /dev/null
@@ -0,0 +1,22 @@
+{
+    "containerConfigs" : [],
+    "foregroundId" : "",
+    "defaultId" : "",
+    "containersPath" : "/tmp/ut-containers",
+    "containerImagePath" : "",
+    "containerTemplatePath" : "templates",
+    "containerNewConfigPrefix" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/",
+    "runMountPointPrefix" : "",
+    "lxcTemplatePrefix" : "@SC_TEST_LXC_TEMPLATES_INSTALL_DIR@",
+    "inputConfig" : {"enabled" : false,
+                     "device" : "/dev/doesnotexist",
+                     "code" : 139,
+                     "numberOfEvents" : 2,
+                     "timeWindowMs" : 500},
+    "proxyCallRules" : [{"caller" : "*",
+                         "target" : "*",
+                         "targetBusName" : "org.tizen.containers.tests",
+                         "targetObjectPath" : "*",
+                         "targetInterface" : "*",
+                         "targetMethod" : "*"}]
+}
diff --git a/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf b/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf
deleted file mode 100644 (file)
index 1229c12..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-    "privilege" : 20,
-    "vt" : -1,
-    "switchToDefaultAfterTimeout" : true,
-    "cpuQuotaForeground" : -1,
-    "cpuQuotaBackground" : 1000,
-    "runMountPoint" : "/tmp/ut-containers-manager/~NAME~-dbus",
-    "enableDbusIntegration" : true,
-    "permittedToSend" : [ "/tmp/.*" ],
-    "permittedToRecv" : [ "/tmp/.*" ]
-}
diff --git a/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf.in b/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf.in
new file mode 100644 (file)
index 0000000..f01cfff
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    "name" : "~NAME~",
+    "lxcTemplate" : "minimal-dbus1.sh",
+    "initWithArgs" : ["/bin/sh", "-c", "trap exit SIGTERM; /usr/bin/dbus-daemon --config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-containers-manager/ut-dbus.conf --fork; read"],
+    "ipv4Gateway" : "",
+    "ipv4" : "",
+    "privilege" : 20,
+    "vt" : -1,
+    "switchToDefaultAfterTimeout" : true,
+    "enableDbusIntegration" : true,
+    "cpuQuotaForeground" : -1,
+    "cpuQuotaBackground" : 1000,
+    "runMountPoint" : "/tmp/ut-run1",
+    "permittedToSend" : [ "/tmp/.*" ],
+    "permittedToRecv" : [ "/tmp/.*" ]
+}
index 399cd12..46f659f 100644 (file)
@@ -62,6 +62,7 @@ namespace {
 
 const std::string TEST_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/test-daemon.conf";
 const std::string TEST_DBUS_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/test-dbus-daemon.conf";
+const std::string EMPTY_DBUS_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/empty-dbus-daemon.conf";
 const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-daemon.conf";
 const std::string BUGGY_FOREGROUND_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-foreground-daemon.conf";
 const std::string BUGGY_DEFAULTID_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-default-daemon.conf";
@@ -85,7 +86,7 @@ public:
     typedef std::function<void(const std::string& argument,
                                MethodResultBuilder::Pointer result
                               )> TestApiMethodCallback;
-    typedef std::function<void()> AddContainerResultCallback;
+    typedef std::function<void()> VoidResultCallback;
 
     typedef std::map<std::string, std::string> Dbuses;
 
@@ -308,8 +309,8 @@ public:
 
     }
 
-    void callAsyncMethodAddContainer(const std::string& id,
-                                     const AddContainerResultCallback& result)
+    void callAsyncMethodCreateContainer(const std::string& id,
+                                        const VoidResultCallback& result)
     {
         auto asyncResult = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
             BOOST_CHECK(g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT));
@@ -321,7 +322,26 @@ public:
         mClient->callMethodAsync(api::host::BUS_NAME,
                                  api::host::OBJECT_PATH,
                                  api::host::INTERFACE,
-                                 api::host::METHOD_ADD_CONTAINER,
+                                 api::host::METHOD_CREATE_CONTAINER,
+                                 parameters,
+                                 "()",
+                                 asyncResult);
+    }
+
+    void callAsyncMethodDestroyContainer(const std::string& id,
+                                     const VoidResultCallback& result)
+    {
+        auto asyncResult = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) {
+            BOOST_CHECK(g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT));
+            result();
+        };
+
+        assert(isHost());
+        GVariant* parameters = g_variant_new("(s)", id.c_str());
+        mClient->callMethodAsync(api::host::BUS_NAME,
+                                 api::host::OBJECT_PATH,
+                                 api::host::INTERFACE,
+                                 api::host::METHOD_DESTROY_CONTAINER,
                                  parameters,
                                  "()",
                                  asyncResult);
@@ -938,32 +958,33 @@ BOOST_AUTO_TEST_CASE(SetActiveContainerTest)
                         DbusException);
 }
 
-//TODO fix it
-//BOOST_AUTO_TEST_CASE(AddContainerTest)
-//{
-//    const std::string newContainerId = "test1234";
-//    const std::vector<std::string> newContainerConfigs = {
-//        TEST_CONTAINER_CONF_PATH + newContainerId + ".conf",
-//    };
-//    FileCleanerRAII cleaner(newContainerConfigs);
-//
-//    ContainersManager cm(TEST_DBUS_CONFIG_PATH);
-//    cm.startAll();
-//
-//    Latch callDone;
-//    auto resultCallback = [&]() {
-//        callDone.set();
-//    };
-//
-//    DbusAccessory dbus(DbusAccessory::HOST_ID);
-//
-//    // create new container
-//    dbus.callAsyncMethodAddContainer(newContainerId, resultCallback);
-//    callDone.wait(EVENT_TIMEOUT);
-//
-//    // focus new container
-//    cm.focus(newContainerId);
-//    BOOST_CHECK(cm.getRunningForegroundContainerId() == newContainerId);
-//}
+BOOST_AUTO_TEST_CASE(CreateDestroyContainerTest)
+{
+    const std::string newContainerId = "test1234";
+
+    ContainersManager cm(EMPTY_DBUS_CONFIG_PATH);
+    cm.startAll();
+
+    Latch callDone;
+    auto resultCallback = [&]() {
+        callDone.set();
+    };
+
+    DbusAccessory dbus(DbusAccessory::HOST_ID);
+
+    // create new container
+    dbus.callAsyncMethodCreateContainer(newContainerId, resultCallback);
+    BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+
+    // focus new container
+    cm.focus(newContainerId);
+    BOOST_CHECK(cm.getRunningForegroundContainerId() == newContainerId);
+
+    // destroy container
+    dbus.callAsyncMethodDestroyContainer(newContainerId, resultCallback);
+    BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT));
+
+    BOOST_CHECK(cm.getRunningForegroundContainerId() == "");
+}
 
 BOOST_AUTO_TEST_SUITE_END()