From 14ad168b8ffff24f1775e497e4762d1682c544f9 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Thu, 27 Nov 2014 16:39:33 +0100 Subject: [PATCH] Support for destroying container [Bug/Feature] N/A [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I4303284b06fdebf452a040c9dfa2c1cddc0b8abf --- cli/command-line-interface.cpp | 11 +++ cli/command-line-interface.hpp | 7 ++ cli/main.cpp | 8 ++ client/security-containers-client-impl.cpp | 9 ++- client/security-containers-client.cpp | 2 +- client/security-containers-client.h | 2 +- server/common-dbus-definitions.hpp | 2 +- server/container-admin.cpp | 14 ++++ server/container-admin.hpp | 6 ++ server/container.cpp | 6 ++ server/container.hpp | 5 ++ server/containers-manager.cpp | 94 +++++++++++++++------- server/containers-manager.hpp | 17 +++- server/host-connection.cpp | 24 ++++-- server/host-connection.hpp | 15 +++- server/host-dbus-definitions.hpp | 9 ++- tests/unit_tests/client/ut-client.cpp | 2 +- tests/unit_tests/server/configs/CMakeLists.txt | 9 ++- .../empty-dbus-daemon.conf.in | 22 +++++ .../ut-containers-manager/templates/template.conf | 11 --- .../templates/template.conf.in | 16 ++++ tests/unit_tests/server/ut-containers-manager.cpp | 83 ++++++++++++------- 22 files changed, 279 insertions(+), 95 deletions(-) create mode 100644 tests/unit_tests/server/configs/ut-containers-manager/empty-dbus-daemon.conf.in delete mode 100644 tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf create mode 100644 tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf.in diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 0549afd..b46871d 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -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; diff --git a/cli/command-line-interface.hpp b/cli/command-line-interface.hpp index 41f5048..360f46c 100644 --- a/cli/command-line-interface.hpp +++ b/cli/command-line-interface.hpp @@ -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 diff --git a/cli/main.cpp b/cli/main.cpp index 774881b..0ceb1e5 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -50,6 +50,14 @@ std::map commands = { } }, { + "destroy_domain", { + destroy_domain, + "destroy_domain container_id", + "Destroy container", + {{"container_id", "id container name"}} + } + }, + { "lock_domain", { lock_domain, "lock_domain container_id", diff --git a/client/security-containers-client-impl.cpp b/client/security-containers-client-impl.cpp index 0f08a02..1a6e999 100644 --- a/client/security-containers-client-impl.cpp +++ b/client/security-containers-client-impl.cpp @@ -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 diff --git a/client/security-containers-client.cpp b/client/security-containers-client.cpp index b96718f..ef571c8 100644 --- a/client/security-containers-client.cpp +++ b/client/security-containers-client.cpp @@ -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); } diff --git a/client/security-containers-client.h b/client/security-containers-client.h index b796c16..e7e738c 100644 --- a/client/security-containers-client.h +++ b/client/security-containers-client.h @@ -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 diff --git a/server/common-dbus-definitions.hpp b/server/common-dbus-definitions.hpp index 14bb037..77d0949 100644 --- a/server/common-dbus-definitions.hpp +++ b/server/common-dbus-definitions.hpp @@ -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"; diff --git a/server/container-admin.cpp b/server/container-admin.cpp index ef8ae0f..65179c3 100644 --- a/server/container-admin.cpp +++ b/server/container-admin.cpp @@ -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); diff --git a/server/container-admin.hpp b/server/container-admin.hpp index 79b0193..f3c9a4f 100644 --- a/server/container-admin.hpp +++ b/server/container-admin.hpp @@ -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); }; diff --git a/server/container.cpp b/server/container.cpp index 80decd5..c371d8a 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -240,6 +240,12 @@ void Container::setDetachOnExit() } } +void Container::setDestroyOnExit() +{ + Lock lock(mReconnectMutex); + mAdmin->setDestroyOnExit(); +} + bool Container::isRunning() { Lock lock(mReconnectMutex); diff --git a/server/container.hpp b/server/container.hpp index 76e098a..bc1303c 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -135,6 +135,11 @@ public: void setDetachOnExit(); /** + * Set if container should be destroyed on exit. + */ + void setDestroyOnExit(); + + /** * @return Is the container running? */ bool isRunning(); diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index def04c2..5a6a32b 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -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 diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 16a8cf5..70637bc 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -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); }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 1b38a9c..b7d72b7 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -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); } } } diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 1dacd11..8392578 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -65,7 +65,10 @@ public: )> SetActiveContainerCallback; typedef std::function AddContainerCallback; + )> CreateContainerCallback; + typedef std::function 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(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index a722aee..b7b49c4 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -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 = " " " " " " - " " + " " + " " + " " + " " " " " " " " diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index d6b3fbb..934a062 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -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 = ""; diff --git a/tests/unit_tests/server/configs/CMakeLists.txt b/tests/unit_tests/server/configs/CMakeLists.txt index 17e10a2..fc73fd4 100644 --- a/tests/unit_tests/server/configs/CMakeLists.txt +++ b/tests/unit_tests/server/configs/CMakeLists.txt @@ -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 index 0000000..82f6c0e --- /dev/null +++ b/tests/unit_tests/server/configs/ut-containers-manager/empty-dbus-daemon.conf.in @@ -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 index 1229c12..0000000 --- a/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf +++ /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 index 0000000..f01cfff --- /dev/null +++ b/tests/unit_tests/server/configs/ut-containers-manager/templates/template.conf.in @@ -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/.*" ] +} diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index 399cd12..46f659f 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -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 TestApiMethodCallback; - typedef std::function AddContainerResultCallback; + typedef std::function VoidResultCallback; typedef std::map 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 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() -- 2.7.4