From d9efc6007505f8ab688a5c75ae8577c0f2c2a330 Mon Sep 17 00:00:00 2001 From: Michal Witanowski Date: Fri, 4 Jul 2014 15:02:46 +0200 Subject: [PATCH 01/16] Fix executable path in systemd service configuration [Bug/Feature] N/A [Cause] "usr" path varies between platforms. [Solution] Generate daemon service path at build time. [Verification] Build and install. Check if value of "ExecStart" in /usr/lib/systemd/system/security-containers.service is valid server executable path. Change-Id: I7cd1bbcaedc3ad2e256c4bbe4210886ba6262813 Signed-off-by: Michal Witanowski --- server/configs/CMakeLists.txt | 11 ++++++++--- ...rity-containers.service => security-containers.service.in} | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) rename server/configs/systemd/{security-containers.service => security-containers.service.in} (76%) diff --git a/server/configs/CMakeLists.txt b/server/configs/CMakeLists.txt index 4a15fe3..0adcd0d 100644 --- a/server/configs/CMakeLists.txt +++ b/server/configs/CMakeLists.txt @@ -21,9 +21,14 @@ MESSAGE(STATUS "Installing configs to " ${SC_CONFIG_INSTALL_DIR}) FILE(GLOB container_CONF containers/*.conf) FILE(GLOB admin_CONF libvirt-config/*.xml) -FILE(GLOB SYSTEMD_SERVICES systemd/*.service) -## Installations ############################################################### + +## Generate #################################################################### +CONFIGURE_FILE(systemd/security-containers.service.in + ${CMAKE_BINARY_DIR}/systemd/security-containers.service) + + +## Install ##################################################################### INSTALL(FILES daemon.conf DESTINATION ${SC_CONFIG_INSTALL_DIR}) @@ -46,5 +51,5 @@ INSTALL(FILES ${container_CONF} INSTALL(FILES ${admin_CONF} DESTINATION ${SC_CONFIG_INSTALL_DIR}/libvirt-config) -INSTALL(FILES ${SYSTEMD_SERVICES} +INSTALL(FILES ${CMAKE_BINARY_DIR}/systemd/security-containers.service DESTINATION ${SYSTEMD_UNIT_DIR}) diff --git a/server/configs/systemd/security-containers.service b/server/configs/systemd/security-containers.service.in similarity index 76% rename from server/configs/systemd/security-containers.service rename to server/configs/systemd/security-containers.service.in index 38e2fd7..f06dea3 100644 --- a/server/configs/systemd/security-containers.service +++ b/server/configs/systemd/security-containers.service.in @@ -5,7 +5,7 @@ Requires=libvirtd.service [Service] Type=simple -ExecStart=/usr/bin/security-containers-server +ExecStart=${CMAKE_INSTALL_PREFIX}/bin/security-containers-server Restart=on-failure ExecReload=/bin/kill -HUP $MAINPID -- 2.7.4 From 109893c909ac071c848315de252fba29691c30e7 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Tue, 1 Jul 2014 15:08:26 +0200 Subject: [PATCH 02/16] Add flag in container config allowing switch to default after timeout [Feature] Flag in container config which allows switching to default container when timeout occurs. [Cause] Some containers might want to forbid switching to default container after timeout. [Solution] Add flag switchToDefaultAfterTimeout allowing such switch in container config. [Verification] Build, install, run tests. All should pass. Change-Id: Icdcfc007c0a11126fe243988878a2c918d6bdf13 Signed-off-by: Lukasz Kostyra --- server/configs/containers/business.conf | 1 + server/configs/containers/private.conf | 1 + server/container-config.hpp | 7 ++++ server/container.cpp | 5 +++ server/container.hpp | 5 +++ server/containers-manager.cpp | 11 ++++- .../ut-container-admin/containers/buggy.conf.in | 1 + .../ut-container-admin/containers/missing.conf | 1 + .../containers/test-no-shutdown.conf.in | 1 + .../ut-container-admin/containers/test.conf.in | 1 + .../configs/ut-container/containers/buggy.conf | 1 + .../configs/ut-container/containers/test-dbus.conf | 1 + .../configs/ut-container/containers/test.conf | 1 + .../containers/console1-dbus.conf | 1 + .../ut-containers-manager/containers/console1.conf | 1 + .../containers/console2-dbus.conf | 1 + .../ut-containers-manager/containers/console2.conf | 1 + .../containers/console3-dbus.conf | 1 + .../ut-containers-manager/containers/console3.conf | 1 + .../ut-network-admin/containers/buggy.conf.in | 1 + .../ut-network-admin/containers/missing.conf | 1 + .../ut-network-admin/containers/test.conf.in | 1 + .../configs/ut-server/containers/container1.conf | 1 + .../configs/ut-server/containers/container2.conf | 1 + .../configs/ut-server/containers/container3.conf | 1 + tests/unit_tests/server/ut-containers-manager.cpp | 48 ++++++++++++++++++++++ 26 files changed, 95 insertions(+), 2 deletions(-) diff --git a/server/configs/containers/business.conf b/server/configs/containers/business.conf index 80efdd4..f16ccb4 100644 --- a/server/configs/containers/business.conf +++ b/server/configs/containers/business.conf @@ -2,6 +2,7 @@ "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, "privilege" : 1, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/business.xml", "networkConfig" : "../libvirt-config/business-network.xml", "runMountPoint" : "business/run", diff --git a/server/configs/containers/private.conf b/server/configs/containers/private.conf index 3984476..cde88c3 100644 --- a/server/configs/containers/private.conf +++ b/server/configs/containers/private.conf @@ -2,6 +2,7 @@ "cpuQuotaForeground" : -1, "cpuQuotaBackground" : 1000, "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/private.xml", "networkConfig" : "../libvirt-config/private-network.xml", "runMountPoint" : "private/run", diff --git a/server/container-config.hpp b/server/container-config.hpp index d5a3038..f5f202e 100644 --- a/server/container-config.hpp +++ b/server/container-config.hpp @@ -43,6 +43,12 @@ struct ContainerConfig { int privilege; /** + * Allow switching to default container after timeout. + * Setting this to false will disable switching to default container after timeout. + */ + bool switchToDefaultAfterTimeout; + + /** * Container's libvirt (XML) config file. * Location can be relative to the Container's config file. */ @@ -83,6 +89,7 @@ struct ContainerConfig { CONFIG_REGISTER ( privilege, + switchToDefaultAfterTimeout, config, networkConfig, cpuQuotaForeground, diff --git a/server/container.cpp b/server/container.cpp index f8a8798..96ca936 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -182,6 +182,11 @@ bool Container::isPaused() return mAdmin->isPaused(); } +bool Container::isSwitchToDefaultAfterTimeoutAllowed() const +{ + return mConfig.switchToDefaultAfterTimeout; +} + void Container::onNameLostCallback() { LOGI(getId() << ": A connection to the DBUS server has been lost, reconnecting..."); diff --git a/server/container.hpp b/server/container.hpp index 8ab37d8..4c1c879 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -129,6 +129,11 @@ public: // ContainerConnection API /** + * @return Is switching to default container after timeout allowed? + */ + bool isSwitchToDefaultAfterTimeoutAllowed() const; + + /** * Register notification request callback */ void setNotifyActiveContainerCallback(const NotifyActiveContainerCallback& callback); diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 2f8e8dd..657c7bf 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -224,8 +224,15 @@ void ContainersManager::notifyActiveContainerHandler(const std::string& caller, void ContainersManager::displayOffHandler(const std::string& /*caller*/) { - LOGI("Switching to default container " << mConfig.defaultId); - focus(mConfig.defaultId); + // get config of currently set container and switch if switchToDefaultAfterTimeout is true + const std::string activeContainerName = getRunningForegroundContainerId(); + const auto& activeContainer = mContainers.find(activeContainerName); + + if (activeContainer != mContainers.end() && + activeContainer->second->isSwitchToDefaultAfterTimeoutAllowed()) { + LOGI("Switching to default container " << mConfig.defaultId); + focus(mConfig.defaultId); + } } void ContainersManager::handleContainerMoveFileRequest(const std::string& srcContainerId, diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in index e06bf63..341052b 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container-admin/libvirt-config/buggy.xml", "networkConfig" : "", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf b/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf index 55d6852..7ac04e9 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "/this/is/a/missing/file/path/missing.xml", "networkConfig" : "", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in index 6d01a50..8f4da35 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container-admin/libvirt-config/test-no-shutdown.xml", "networkConfig" : "", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in index 518aa4c..badc3da 100644 --- a/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in +++ b/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container-admin/libvirt-config/test.xml", "networkConfig" : "", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container/containers/buggy.conf b/tests/unit_tests/server/configs/ut-container/containers/buggy.conf index d5ccd1e..0dc866a 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/buggy.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/buggy.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "/missing/file/path/libvirt.xml", "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf b/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf index fde05d8..bf35f07 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/test-dbus.xml", "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-container/containers/test.conf b/tests/unit_tests/server/configs/ut-container/containers/test.conf index e1769c3..dc81e44 100644 --- a/tests/unit_tests/server/configs/ut-container/containers/test.conf +++ b/tests/unit_tests/server/configs/ut-container/containers/test.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/test.xml", "networkConfig" : "../libvirt-config/network.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf index 55dfeb5..ef49f19 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1-dbus.conf @@ -1,5 +1,6 @@ { "privilege" : 20, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/console1-dbus.xml", "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf index 61668c8..b26e02e 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf @@ -1,5 +1,6 @@ { "privilege" : 20, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/console1.xml", "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf index 713cb02..76c5e49 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2-dbus.conf @@ -1,5 +1,6 @@ { "privilege" : 20, + "switchToDefaultAfterTimeout" : false, "config" : "../libvirt-config/console2-dbus.xml", "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf index 10e5cef..f609a85 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/console2.xml", "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf index 70ff251..592cbfa 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3-dbus.conf @@ -1,5 +1,6 @@ { "privilege" : 20, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/console3-dbus.xml", "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf index 8ccf55b..e249df7 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf @@ -1,5 +1,6 @@ { "privilege" : 15, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/console3.xml", "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in b/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in index be3f7c1..2b88e29 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/buggy.conf.in @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "", "networkConfig" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-network-admin/libvirt-config/buggy-network.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf b/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf index f418503..ca580a1 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/missing.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "", "networkConfig" : "", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in b/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in index 771a93b..547c6cd 100644 --- a/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in +++ b/tests/unit_tests/server/configs/ut-network-admin/containers/test.conf.in @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "", "networkConfig" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-network-admin/libvirt-config/network.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-server/containers/container1.conf b/tests/unit_tests/server/configs/ut-server/containers/container1.conf index 952decf..f93690a 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container1.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container1.conf @@ -1,5 +1,6 @@ { "privilege" : 20, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/container1.xml", "networkConfig" : "../libvirt-config/network1.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-server/containers/container2.conf b/tests/unit_tests/server/configs/ut-server/containers/container2.conf index 4e6de09..f519018 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container2.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container2.conf @@ -1,5 +1,6 @@ { "privilege" : 10, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/container2.xml", "networkConfig" : "../libvirt-config/network2.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/configs/ut-server/containers/container3.conf b/tests/unit_tests/server/configs/ut-server/containers/container3.conf index 9170c54..3c5989e 100644 --- a/tests/unit_tests/server/configs/ut-server/containers/container3.conf +++ b/tests/unit_tests/server/configs/ut-server/containers/container3.conf @@ -1,5 +1,6 @@ { "privilege" : 15, + "switchToDefaultAfterTimeout" : true, "config" : "../libvirt-config/container3.xml", "networkConfig" : "../libvirt-config/network3.xml", "cpuQuotaForeground" : -1, diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index 0182cb8..bf91d9f 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -448,5 +448,53 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) fs::remove_all(CONTAINER2PATH, ec); } +BOOST_AUTO_TEST_CASE(AllowSwitchToDefaultTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + BOOST_REQUIRE_NO_THROW(cm.startAll()); + + std::vector> clients; + for (int i = 1; i <= TEST_DBUS_CONNECTION_CONTAINERS_COUNT; ++i) { + clients.push_back(std::unique_ptr(new DbusAccessory(i))); + } + + for (auto& client : clients) { + client->setName(fake_power_manager_api::BUS_NAME); + } + + std::mutex condMutex; + std::unique_lock condLock(condMutex); + std::condition_variable condition; + auto cond = [&cm]() -> bool { + return cm.getRunningForegroundContainerId() == "ut-containers-manager-console1-dbus"; + }; + + for (auto& client : clients) { + // focus non-default container with allowed switching + BOOST_REQUIRE_NO_THROW(cm.focus("ut-containers-manager-console3-dbus")); + + // emit signal from dbus connection + BOOST_REQUIRE_NO_THROW(client->emitSignal(fake_power_manager_api::OBJECT_PATH, + fake_power_manager_api::INTERFACE, + fake_power_manager_api::SIGNAL_DISPLAY_OFF, + nullptr)); + + // check if default container has focus + BOOST_CHECK(condition.wait_for(condLock, std::chrono::milliseconds(EVENT_TIMEOUT), cond)); + + // focus non-default container with disabled switching + BOOST_REQUIRE_NO_THROW(cm.focus("ut-containers-manager-console2-dbus")); + + // emit signal from dbus connection + BOOST_REQUIRE_NO_THROW(client->emitSignal(fake_power_manager_api::OBJECT_PATH, + fake_power_manager_api::INTERFACE, + fake_power_manager_api::SIGNAL_DISPLAY_OFF, + nullptr)); + + // now default container should not be focused + BOOST_CHECK(!condition.wait_for(condLock, std::chrono::milliseconds(EVENT_TIMEOUT), cond)); + } +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 14f5261f7ce584f000adabc79a004e5d9207ad2c Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Tue, 8 Jul 2014 11:31:31 +0200 Subject: [PATCH 03/16] Containers support package [Bug/Feature] New package to be installed in every container. It replaces image-skel dir. [Cause] N/A [Solution] N/A [Verification] Build, install container-support and container-daemon inside container, install rest packages on host, verify scs works. Change-Id: Ia03a6481d1fe72375cec751701ac9eba1d6cc97c --- CMakeLists.txt | 2 ++ container-support/CMakeLists.txt | 29 ++++++++++++++++++++++ .../configs}/org.tizen.containers.domain.conf.in | 0 .../security-containers-container-support.manifest | 5 ++++ packaging/security-containers.spec | 20 +++++++++++++-- server/configs/CMakeLists.txt | 6 ----- 6 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 container-support/CMakeLists.txt rename {server/configs/image-skel/etc/dbus-1/system.d => container-support/configs}/org.tizen.containers.domain.conf.in (100%) create mode 100644 packaging/security-containers-container-support.manifest diff --git a/CMakeLists.txt b/CMakeLists.txt index e5bc053..266773a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,7 @@ ENDIF(NOT DEFINED PYTHON_SITELIB) SET(COMMON_FOLDER ${PROJECT_SOURCE_DIR}/common) SET(CLIENT_FOLDER ${PROJECT_SOURCE_DIR}/client) SET(SERVER_FOLDER ${PROJECT_SOURCE_DIR}/server) +SET(CONTAINER_SUPPORT_FOLDER ${PROJECT_SOURCE_DIR}/container-support) SET(CONTAINER_DAEMON_FOLDER ${PROJECT_SOURCE_DIR}/container-daemon) SET(TESTS_FOLDER ${PROJECT_SOURCE_DIR}/tests) SET(UNIT_TESTS_FOLDER ${TESTS_FOLDER}/unit_tests) @@ -120,6 +121,7 @@ SET(SC_DATA_INSTALL_DIR ${SHARE_INSTALL_PREFIX}/security-containers) ADD_SUBDIRECTORY(${CLIENT_FOLDER}) ADD_SUBDIRECTORY(${SERVER_FOLDER}) +ADD_SUBDIRECTORY(${CONTAINER_SUPPORT_FOLDER}) ADD_SUBDIRECTORY(${CONTAINER_DAEMON_FOLDER}) ADD_SUBDIRECTORY(${TESTS_FOLDER}) diff --git a/container-support/CMakeLists.txt b/container-support/CMakeLists.txt new file mode 100644 index 0000000..8d9c159 --- /dev/null +++ b/container-support/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# @file CMakeLists.txt +# @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) +# + +MESSAGE(STATUS "Generating makefile for the Container Support...") + + +## Install ##################################################################### + +CONFIGURE_FILE(configs/org.tizen.containers.domain.conf.in + ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.containers.domain.conf) + +INSTALL(FILES ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.containers.domain.conf + DESTINATION /etc/dbus-1/system.d/) diff --git a/server/configs/image-skel/etc/dbus-1/system.d/org.tizen.containers.domain.conf.in b/container-support/configs/org.tizen.containers.domain.conf.in similarity index 100% rename from server/configs/image-skel/etc/dbus-1/system.d/org.tizen.containers.domain.conf.in rename to container-support/configs/org.tizen.containers.domain.conf.in diff --git a/packaging/security-containers-container-support.manifest b/packaging/security-containers-container-support.manifest new file mode 100644 index 0000000..2a0cec5 --- /dev/null +++ b/packaging/security-containers-container-support.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index e214d14..1258c1a 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -39,7 +39,6 @@ between them. A process from inside a container can request a switch of context %config /etc/security-containers/daemon.conf %config /etc/security-containers/containers/*.conf %config /etc/security-containers/libvirt-config/*.xml -/etc/security-containers/image-skel %{_unitdir}/security-containers.service %{_unitdir}/multi-user.target.wants/security-containers.service /etc/dbus-1/system.d/org.tizen.containers.host.conf @@ -134,11 +133,28 @@ Development package including the header files for the client library %{_libdir}/pkgconfig/* +## Container Support Package ################################################### +# TODO move to a separate repository +%package container-support +Summary: Security Containers Support +Group: Security/Other +Conflicts: security-containers + +%description container-support +Containers support installed inside every container. + +%files container-support +%manifest packaging/security-containers-container-support.manifest +%defattr(644,root,root,755) +/etc/dbus-1/system.d/org.tizen.containers.domain.conf + + ## Container Daemon Package #################################################### +# TODO move to a separate repository %package container-daemon Summary: Security Containers Containers Daemon Group: Security/Other -Requires: security-containers = %{version}-%{release} +Requires: security-containers-container-support = %{version}-%{release} %description container-daemon Daemon running inside every container. diff --git a/server/configs/CMakeLists.txt b/server/configs/CMakeLists.txt index 0adcd0d..def06a2 100644 --- a/server/configs/CMakeLists.txt +++ b/server/configs/CMakeLists.txt @@ -35,12 +35,6 @@ INSTALL(FILES daemon.conf # preprocess d-bus configs CONFIGURE_FILE(dbus-1/system.d/org.tizen.containers.host.conf.in ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.containers.host.conf) -CONFIGURE_FILE(image-skel/etc/dbus-1/system.d/org.tizen.containers.domain.conf.in - ${CMAKE_BINARY_DIR}/image-skel/etc/dbus-1/system.d/org.tizen.containers.domain.conf) - -# TODO This file should be installed to /etc/dbus-1/system.d/ on an every container -INSTALL(FILES ${CMAKE_BINARY_DIR}/image-skel/etc/dbus-1/system.d/org.tizen.containers.domain.conf - DESTINATION ${SC_CONFIG_INSTALL_DIR}/image-skel/etc/dbus-1/system.d) INSTALL(FILES ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.containers.host.conf DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d/) -- 2.7.4 From 23cb74030a60c0a0d794b320a451397a559b4f02 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Mon, 14 Jul 2014 12:33:03 +0200 Subject: [PATCH 04/16] Update input monitor configuration sequence [Bug] Input monitor detected double-pressing, which caused errors. [Cause] Some systems already used double-press as a pattern. [Solution] Change input sequence from double press to triple press. [Verification] Build, install, run SCS with -l TRACE. Run journalctl --unit=security-containers --follow -l Press "HOME" key three times quickly - you should see entries: "Event sequence detected" "Input monitor detected pattern" "switchingSequenceMonitorNotify() called" Change-Id: I52850851f1c72326d50b796d651886c7eec3406c Signed-off-by: Lukasz Kostyra --- server/configs/daemon.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/configs/daemon.conf b/server/configs/daemon.conf index c67f607..9c0eba6 100644 --- a/server/configs/daemon.conf +++ b/server/configs/daemon.conf @@ -7,6 +7,6 @@ "inputConfig" : {"enabled" : true, "device" : "gpio-keys", "code" : 139, - "numberOfEvents" : 2, + "numberOfEvents" : 3, "timeWindowMs" : 500} } -- 2.7.4 From ef1c5e0915624562910c91855d53c5b834d90bca Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Fri, 11 Jul 2014 16:38:19 +0200 Subject: [PATCH 05/16] Dbus async method call [Bug/Feature] Async version of dbus method call added. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I90bb5d1816a95f9619e2a4b88dd63c9ebd4b64da --- common/dbus/connection.cpp | 70 ++++++++++++++++- common/dbus/connection.hpp | 26 +++++++ common/utils/scoped-gerror.cpp | 5 ++ common/utils/scoped-gerror.hpp | 5 ++ tests/unit_tests/dbus/test-server.cpp | 2 +- tests/unit_tests/dbus/ut-connection.cpp | 130 +++++++++++++++++++++++++++++--- 6 files changed, 225 insertions(+), 13 deletions(-) diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp index 479c253..4a4a2cd 100644 --- a/common/dbus/connection.cpp +++ b/common/dbus/connection.cpp @@ -87,6 +87,28 @@ void throwDbusException(const ScopedGError& e) } } +class AsyncMethodCallResultImpl : public AsyncMethodCallResult { +public: + AsyncMethodCallResultImpl(GVariant* result, const ScopedGError& error) + : mResult(result), mError(error) {} + ~AsyncMethodCallResultImpl() + { + if (mResult) { + g_variant_unref(mResult); + } + } + GVariant* get() + { + if (mError) { + throwDbusException(mError); + } + return mResult; + } +private: + GVariant* mResult; + const ScopedGError& mError; +}; + } // namespace DbusConnection::Pointer DbusConnection::create(const std::string& address) @@ -308,7 +330,8 @@ GVariantPtr DbusConnection::callMethod(const std::string& busName, interface.c_str(), method.c_str(), parameters, - G_VARIANT_TYPE(replyType.c_str()), + replyType.empty() ? NULL + : G_VARIANT_TYPE(replyType.c_str()), G_DBUS_CALL_FLAGS_NONE, CALL_METHOD_TIMEOUT_MS, NULL, @@ -321,6 +344,51 @@ GVariantPtr DbusConnection::callMethod(const std::string& busName, return GVariantPtr(result, g_variant_unref); } +void DbusConnection::callMethodAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const std::string& replyType, + const AsyncMethodCallCallback& callback) +{ + g_dbus_connection_call(mConnection, + busName.c_str(), + objectPath.c_str(), + interface.c_str(), + method.c_str(), + parameters, + replyType.empty() ? NULL + : G_VARIANT_TYPE(replyType.c_str()), + G_DBUS_CALL_FLAGS_NONE, + CALL_METHOD_TIMEOUT_MS, + NULL, + &DbusConnection::onAsyncReady, + utils::createCallbackWrapper(callback, mGuard.spawn())); +} + +void DbusConnection::onAsyncReady(GObject* source, + GAsyncResult* asyncResult, + gpointer userData) +{ + std::unique_ptr + autoDeleteCallback(userData, &utils::deleteCallbackWrapper); + GDBusConnection* connection = reinterpret_cast(source); + const AsyncMethodCallCallback& callback = + utils::getCallbackFromPointer(userData); + + ScopedGError error; + GVariant* result = g_dbus_connection_call_finish(connection, asyncResult, &error); + if (error) { + error.strip(); + LOGE("Call method failed; " << error); + } + AsyncMethodCallResultImpl asyncMethodCallResult(result, error); + if (callback) { + callback(asyncMethodCallResult); + } +} + } // namespace dbus } // namespace security_containers diff --git a/common/dbus/connection.hpp b/common/dbus/connection.hpp index cbdbdf5..28932af 100644 --- a/common/dbus/connection.hpp +++ b/common/dbus/connection.hpp @@ -51,6 +51,15 @@ public: }; /** + * An interface used to get result from async response. + */ +class AsyncMethodCallResult { +public: + virtual ~AsyncMethodCallResult() {} + virtual GVariant* get() = 0; // throws DbusException on error +}; + +/** * Dbus connection. * Provides a functionality that allows to call dbus methods, * register dbus interfaces, etc. @@ -77,6 +86,9 @@ public: GVariant* parameters )> SignalCallback; + typedef std::function AsyncMethodCallCallback; + /** * Creates a connection to the dbus with given address. */ @@ -130,6 +142,17 @@ public: const std::string& replyType); /** + * Async call a dbus method + */ + void callMethodAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const std::string& replyType, + const AsyncMethodCallCallback& callback); + + /** * Returns an xml with meta description of specified dbus object. */ std::string introspect(const std::string& busName, const std::string& objectPath); @@ -166,6 +189,9 @@ private: GVariant* parameters, GDBusMethodInvocation* invocation, gpointer userData); + static void onAsyncReady(GObject* source, + GAsyncResult* asyncResult, + gpointer userData); }; diff --git a/common/utils/scoped-gerror.cpp b/common/utils/scoped-gerror.cpp index 303dd4e..7ce85d4 100644 --- a/common/utils/scoped-gerror.cpp +++ b/common/utils/scoped-gerror.cpp @@ -32,7 +32,12 @@ namespace utils { ScopedGError::ScopedGError() : mError(NULL) { +} +ScopedGError::ScopedGError(ScopedGError&& other) + : mError(other.mError) +{ + other.mError = NULL; } ScopedGError::~ScopedGError() diff --git a/common/utils/scoped-gerror.hpp b/common/utils/scoped-gerror.hpp index 06e17aa..6df8085 100644 --- a/common/utils/scoped-gerror.hpp +++ b/common/utils/scoped-gerror.hpp @@ -34,8 +34,12 @@ namespace utils { class ScopedGError { public: ScopedGError(); + ScopedGError(ScopedGError&&); ~ScopedGError(); + ScopedGError(const ScopedGError&) = delete; + ScopedGError& operator=(const ScopedGError&) = delete; + /** * Strip the error */ @@ -65,6 +69,7 @@ public: private: GError* mError; + }; } // namespace utils diff --git a/tests/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp index 6fcbbda..711f16f 100644 --- a/tests/unit_tests/dbus/test-server.cpp +++ b/tests/unit_tests/dbus/test-server.cpp @@ -142,7 +142,7 @@ void DbusTestServer::onMessageCall(const std::string& objectPath, LOGE("unknown method; should never happen"); } } catch (const std::exception& e) { - result.setError("org.tizen.Exception", e.what()); + result.setError("org.tizen.containers.Error.Test", e.what()); } } diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 46b9aa9..131e359 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -325,21 +325,129 @@ BOOST_AUTO_TEST_CASE(MethodCallTest) const std::string& methodName, GVariant* parameters, MethodResultBuilder& result) { - if (objectPath == TESTAPI_OBJECT_PATH && - interface == TESTAPI_INTERFACE && - methodName == TESTAPI_METHOD_NOOP && - g_variant_is_of_type(parameters, G_VARIANT_TYPE_UNIT)) { + if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { + return; + } + if (methodName == TESTAPI_METHOD_NOOP) { result.setVoid(); + } else if (methodName == TESTAPI_METHOD_PROCESS) { + const gchar* arg = NULL; + g_variant_get(parameters, "(&s)", &arg); + std::string str = std::string("resp: ") + arg; + result.set(g_variant_new("(s)", str.c_str())); + } else if (methodName == TESTAPI_METHOD_THROW) { + int arg = 0; + g_variant_get(parameters, "(i)", &arg); + result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); } }; conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); - GVariantPtr result = conn2->callMethod(TESTAPI_BUS_NAME, - TESTAPI_OBJECT_PATH, - TESTAPI_INTERFACE, - TESTAPI_METHOD_NOOP, - NULL, - "()"); - BOOST_CHECK(g_variant_is_of_type(result.get(), G_VARIANT_TYPE_UNIT)); + + GVariantPtr result1 = conn2->callMethod(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_NOOP, + NULL, + "()"); + BOOST_CHECK(g_variant_is_of_type(result1.get(), G_VARIANT_TYPE_UNIT)); + + GVariantPtr result2 = conn2->callMethod(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_PROCESS, + g_variant_new("(s)", "arg"), + "(s)"); + const gchar* ret2 = NULL; + g_variant_get(result2.get(), "(&s)", &ret2); + BOOST_CHECK_EQUAL("resp: arg", ret2); + + BOOST_CHECK_THROW(conn2->callMethod(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_THROW, + g_variant_new("(i)", 7), + "()"), + DbusCustomException); +} + +BOOST_AUTO_TEST_CASE(MethodAsyncCallTest) +{ + ScopedDbusDaemon daemon; + ScopedGlibLoop loop; + Latch nameAcquired; + + DbusConnection::Pointer conn1 = DbusConnection::create(DBUS_ADDRESS); + DbusConnection::Pointer conn2 = DbusConnection::create(DBUS_ADDRESS); + + conn1->setName(TESTAPI_BUS_NAME, + [&] {nameAcquired.set();}, + [] {}); + BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT)); + auto handler = [](const std::string& objectPath, + const std::string& interface, + const std::string& methodName, + GVariant* parameters, + MethodResultBuilder& result) { + if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { + return; + } + if (methodName == TESTAPI_METHOD_NOOP) { + result.setVoid(); + } else if (methodName == TESTAPI_METHOD_PROCESS) { + const gchar* arg = NULL; + g_variant_get(parameters, "(&s)", &arg); + std::string str = std::string("resp: ") + arg; + result.set(g_variant_new("(s)", str.c_str())); + } else if (methodName == TESTAPI_METHOD_THROW) { + int arg = 0; + g_variant_get(parameters, "(i)", &arg); + result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); + } + }; + conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); + + Latch callDone; + + auto asyncResult1 = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + BOOST_CHECK(g_variant_is_of_type(asyncMethodCallResult.get(), G_VARIANT_TYPE_UNIT)); + callDone.set(); + }; + conn2->callMethodAsync(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_NOOP, + NULL, + "()", + asyncResult1); + BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); + + auto asyncResult2 = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + const gchar* ret = NULL; + g_variant_get(asyncMethodCallResult.get(), "(&s)", &ret); + BOOST_CHECK_EQUAL("resp: arg", ret); + callDone.set(); + }; + conn2->callMethodAsync(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_PROCESS, + g_variant_new("(s)", "arg"), + "(s)", + asyncResult2); + BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); + + auto asyncResult3 = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + BOOST_CHECK_THROW(asyncMethodCallResult.get(), DbusCustomException); + callDone.set(); + }; + conn2->callMethodAsync(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_THROW, + g_variant_new("(i)", 7), + "()", + asyncResult3); + BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); } BOOST_AUTO_TEST_CASE(MethodCallExceptionTest) -- 2.7.4 From af83a11b30b0cb761b1fbb178652416339534be7 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Tue, 15 Jul 2014 16:51:26 +0200 Subject: [PATCH 06/16] Dbus async method call handler [Bug/Feature] Enable deferred set of result in dbus method handler. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I11b3abe0886bc560f8b63f6206c64695f2f7eb1a --- common/dbus/connection.cpp | 17 ++++---- common/dbus/connection.hpp | 4 +- container-daemon/daemon-connection.cpp | 6 +-- container-daemon/daemon-connection.hpp | 2 +- server/container-connection.cpp | 4 +- server/container-connection.hpp | 4 +- server/containers-manager.cpp | 14 +++---- server/containers-manager.hpp | 2 +- server/host-connection.cpp | 4 +- server/host-connection.hpp | 2 +- tests/unit_tests/dbus/test-server.cpp | 10 ++--- tests/unit_tests/dbus/test-server.hpp | 2 +- tests/unit_tests/dbus/ut-connection.cpp | 73 +++++++++++++++++++++++++++++---- 13 files changed, 100 insertions(+), 44 deletions(-) diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp index 4a4a2cd..ef6fc46 100644 --- a/common/dbus/connection.cpp +++ b/common/dbus/connection.cpp @@ -47,6 +47,12 @@ class MethodResultBuilderImpl : public MethodResultBuilder { public: MethodResultBuilderImpl(GDBusMethodInvocation* invocation) : mInvocation(invocation), mResultSet(false) {} + ~MethodResultBuilderImpl() + { + if (!mResultSet) { + setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented"); + } + } void set(GVariant* parameters) { g_dbus_method_invocation_return_value(mInvocation, parameters); @@ -61,10 +67,6 @@ public: g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str()); mResultSet = true; } - bool isUndefined() const - { - return !mResultSet; - } private: GDBusMethodInvocation* mInvocation; bool mResultSet; @@ -305,15 +307,10 @@ void DbusConnection::onMethodCall(GDBusConnection*, LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method); - MethodResultBuilderImpl resultBuilder(invocation); + MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation)); if (callback) { callback(objectPath, interface, method, parameters, resultBuilder); } - - if (resultBuilder.isUndefined()) { - LOGW("Unimplemented method: " << objectPath << "; " << interface << "; " << method); - resultBuilder.setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented"); - } } GVariantPtr DbusConnection::callMethod(const std::string& busName, diff --git a/common/dbus/connection.hpp b/common/dbus/connection.hpp index 28932af..9ac87de 100644 --- a/common/dbus/connection.hpp +++ b/common/dbus/connection.hpp @@ -44,6 +44,8 @@ typedef std::unique_ptr GVariantPtr; */ class MethodResultBuilder { public: + typedef std::shared_ptr Pointer; + virtual ~MethodResultBuilder() {} virtual void set(GVariant* parameters) = 0; virtual void setVoid() = 0; @@ -76,7 +78,7 @@ public: const std::string& interface, const std::string& methodName, GVariant* parameters, - MethodResultBuilder& result + MethodResultBuilder::Pointer result )> MethodCallCallback; typedef std::functionsetVoid(); } } else if (methodName == api::METHOD_LOSE_FOCUS) { if (mLoseFocusCallback) { mLoseFocusCallback(); - result.setVoid(); + result->setVoid(); } } } diff --git a/container-daemon/daemon-connection.hpp b/container-daemon/daemon-connection.hpp index e2e5154..34129df 100644 --- a/container-daemon/daemon-connection.hpp +++ b/container-daemon/daemon-connection.hpp @@ -68,7 +68,7 @@ private: const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result); + dbus::MethodResultBuilder::Pointer result); }; diff --git a/server/container-connection.cpp b/server/container-connection.cpp index 3ef2dd7..adabace 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -150,7 +150,7 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result) + dbus::MethodResultBuilder::Pointer result) { if (objectPath != api::OBJECT_PATH || interface != api::INTERFACE) { return; @@ -162,7 +162,7 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, g_variant_get(parameters, "(&s&s)", &application, &message); if (mNotifyActiveContainerCallback) { mNotifyActiveContainerCallback(application, message); - result.setVoid(); + result->setVoid(); } } diff --git a/server/container-connection.hpp b/server/container-connection.hpp index 2f429ce..7759a09 100644 --- a/server/container-connection.hpp +++ b/server/container-connection.hpp @@ -52,7 +52,7 @@ public: typedef std::function FileMoveRequestCallback; /** @@ -96,7 +96,7 @@ private: const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result); + dbus::MethodResultBuilder::Pointer result); void onSignalReceived(const std::string& senderBusName, const std::string& objectPath, const std::string& interface, diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 657c7bf..0150e4a 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -238,7 +238,7 @@ void ContainersManager::displayOffHandler(const std::string& /*caller*/) void ContainersManager::handleContainerMoveFileRequest(const std::string& srcContainerId, const std::string& dstContainerId, const std::string& path, - dbus::MethodResultBuilder& result) + dbus::MethodResultBuilder::Pointer result) { // TODO: this implementation is only a placeholder. // There are too many unanswered questions and security concerns: @@ -274,26 +274,26 @@ void ContainersManager::handleContainerMoveFileRequest(const std::string& srcCon ContainerMap::const_iterator dstIter = mContainers.find(dstContainerId); if (dstIter == mContainers.end()) { LOGE("Destination container '" << dstContainerId << "' not found"); - result.set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); return; } Container& dstContanier = *dstIter->second; if (srcContainerId == dstContainerId) { LOGE("Cannot send a file to yourself"); - result.set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str())); return; } if (!regexMatchVector(path, srcContainer.getPermittedToSend())) { LOGE("Source container has no permissions to send the file: " << path); - result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); return; } if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) { LOGE("Destination container has no permissions to receive the file: " << path); - result.set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); return; } @@ -303,9 +303,9 @@ void ContainersManager::handleContainerMoveFileRequest(const std::string& srcCon if (!utils::moveFile(srcPath, dstPath)) { LOGE("Failed to move the file: " << path); - result.set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str())); } else { - result.set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str())); + result->set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str())); try { dstContanier.sendNotification(srcContainerId, path, api::FILE_MOVE_SUCCEEDED); } catch (ServerException&) { diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 32ca341..1e29ed7 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -91,7 +91,7 @@ private: void handleContainerMoveFileRequest(const std::string& srcContainerId, const std::string& dstContainerId, const std::string& path, - dbus::MethodResultBuilder& result); + dbus::MethodResultBuilder::Pointer result); }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 4b3c59d..4f9a2f2 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -119,7 +119,7 @@ void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, GVariant* /*parameters*/, - dbus::MethodResultBuilder& result) + dbus::MethodResultBuilder::Pointer result) { if (objectPath != hostapi::OBJECT_PATH || interface != hostapi::INTERFACE) { return; @@ -128,7 +128,7 @@ void HostConnection::onMessageCall(const std::string& objectPath, if (methodName == hostapi::METHOD_TEST) { if (mTestCallback) { mTestCallback(); - result.setVoid(); + result->setVoid(); } } } diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 4d7eccd..d78949f 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -66,7 +66,7 @@ private: const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result); + dbus::MethodResultBuilder::Pointer result); }; diff --git a/tests/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp index 711f16f..3a77390 100644 --- a/tests/unit_tests/dbus/test-server.cpp +++ b/tests/unit_tests/dbus/test-server.cpp @@ -117,7 +117,7 @@ void DbusTestServer::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result) + dbus::MethodResultBuilder::Pointer result) { try { if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { @@ -126,23 +126,23 @@ void DbusTestServer::onMessageCall(const std::string& objectPath, if (methodName == TESTAPI_METHOD_NOOP) { noop(); - result.setVoid(); + result->setVoid(); } else if (methodName == TESTAPI_METHOD_PROCESS) { const gchar* arg; g_variant_get(parameters, "(&s)", &arg); std::string ret = process(arg); GVariant* variant = g_variant_new("(s)", ret.c_str()); - result.set(variant); + result->set(variant); } else if (methodName == TESTAPI_METHOD_THROW) { int arg; g_variant_get(parameters, "(i)", &arg); throwException(arg); - result.setVoid(); + result->setVoid(); } else { LOGE("unknown method; should never happen"); } } catch (const std::exception& e) { - result.setError("org.tizen.containers.Error.Test", e.what()); + result->setError("org.tizen.containers.Error.Test", e.what()); } } diff --git a/tests/unit_tests/dbus/test-server.hpp b/tests/unit_tests/dbus/test-server.hpp index b52ebb3..8e2aa7f 100644 --- a/tests/unit_tests/dbus/test-server.hpp +++ b/tests/unit_tests/dbus/test-server.hpp @@ -73,7 +73,7 @@ private: const std::string& interface, const std::string& methodName, GVariant* parameters, - dbus::MethodResultBuilder& result); + dbus::MethodResultBuilder::Pointer result); }; diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 131e359..21be1e8 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -324,21 +324,21 @@ BOOST_AUTO_TEST_CASE(MethodCallTest) const std::string& interface, const std::string& methodName, GVariant* parameters, - MethodResultBuilder& result) { + MethodResultBuilder::Pointer result) { if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { return; } if (methodName == TESTAPI_METHOD_NOOP) { - result.setVoid(); + result->setVoid(); } else if (methodName == TESTAPI_METHOD_PROCESS) { const gchar* arg = NULL; g_variant_get(parameters, "(&s)", &arg); std::string str = std::string("resp: ") + arg; - result.set(g_variant_new("(s)", str.c_str())); + result->set(g_variant_new("(s)", str.c_str())); } else if (methodName == TESTAPI_METHOD_THROW) { int arg = 0; g_variant_get(parameters, "(i)", &arg); - result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); + result->setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); } }; conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); @@ -387,21 +387,21 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallTest) const std::string& interface, const std::string& methodName, GVariant* parameters, - MethodResultBuilder& result) { + MethodResultBuilder::Pointer result) { if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { return; } if (methodName == TESTAPI_METHOD_NOOP) { - result.setVoid(); + result->setVoid(); } else if (methodName == TESTAPI_METHOD_PROCESS) { const gchar* arg = NULL; g_variant_get(parameters, "(&s)", &arg); std::string str = std::string("resp: ") + arg; - result.set(g_variant_new("(s)", str.c_str())); + result->set(g_variant_new("(s)", str.c_str())); } else if (methodName == TESTAPI_METHOD_THROW) { int arg = 0; g_variant_get(parameters, "(i)", &arg); - result.setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); + result->setError("org.tizen.containers.Error.Test", "msg: " + std::to_string(arg)); } }; conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); @@ -450,6 +450,63 @@ BOOST_AUTO_TEST_CASE(MethodAsyncCallTest) BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); } +BOOST_AUTO_TEST_CASE(MethodAsyncCallAsyncHandlerTest) +{ + ScopedDbusDaemon daemon; + ScopedGlibLoop loop; + Latch nameAcquired; + + DbusConnection::Pointer conn1 = DbusConnection::create(DBUS_ADDRESS); + DbusConnection::Pointer conn2 = DbusConnection::create(DBUS_ADDRESS); + + conn1->setName(TESTAPI_BUS_NAME, + [&] {nameAcquired.set();}, + [] {}); + BOOST_REQUIRE(nameAcquired.wait(EVENT_TIMEOUT)); + + Latch handlerDone; + std::string strResult; + MethodResultBuilder::Pointer deferredResult; + + auto handler = [&](const std::string& objectPath, + const std::string& interface, + const std::string& methodName, + GVariant* parameters, + MethodResultBuilder::Pointer result) { + if (objectPath != TESTAPI_OBJECT_PATH || interface != TESTAPI_INTERFACE) { + return; + } + if (methodName == TESTAPI_METHOD_PROCESS) { + const gchar* arg = NULL; + g_variant_get(parameters, "(&s)", &arg); + strResult = std::string("resp: ") + arg; + deferredResult = result; + handlerDone.set(); + } + }; + conn1->registerObject(TESTAPI_OBJECT_PATH, TESTAPI_DEFINITION, handler); + + Latch callDone; + + auto asyncResult = [&](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + const gchar* ret = NULL; + g_variant_get(asyncMethodCallResult.get(), "(&s)", &ret); + BOOST_CHECK_EQUAL("resp: arg", ret); + callDone.set(); + }; + conn2->callMethodAsync(TESTAPI_BUS_NAME, + TESTAPI_OBJECT_PATH, + TESTAPI_INTERFACE, + TESTAPI_METHOD_PROCESS, + g_variant_new("(s)", "arg"), + "(s)", + asyncResult); + BOOST_REQUIRE(handlerDone.wait(EVENT_TIMEOUT)); + BOOST_REQUIRE(callDone.empty()); + deferredResult->set(g_variant_new("(s)", strResult.c_str())); + BOOST_REQUIRE(callDone.wait(EVENT_TIMEOUT)); +} + BOOST_AUTO_TEST_CASE(MethodCallExceptionTest) { ScopedDbusDaemon daemon; -- 2.7.4 From 0ff2f654b7edccd033abaca73863ef1e5f097855 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Tue, 15 Jul 2014 15:24:26 +0200 Subject: [PATCH 07/16] Dbus proxy call support [Bug/Feature] Introduce the API for communication between services inside container and services in host. SCS works as a router/proxy enabling host <-> container and container <-> container dbus calls. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Ia85a7c0234880069653d1a8596dbc240fa7b3f76 --- packaging/security-containers.spec | 1 + server/configs/daemon.conf | 3 +- server/container-connection.cpp | 49 +++++++ server/container-connection.hpp | 25 ++++ server/container-dbus-definitions.hpp | 10 ++ server/container.cpp | 33 +++++ server/container.hpp | 17 +++ server/containers-manager-config.hpp | 9 +- server/containers-manager.cpp | 81 ++++++++++- server/containers-manager.hpp | 13 +- server/host-connection.cpp | 51 ++++++- server/host-connection.hpp | 24 +++- server/host-dbus-definitions.hpp | 13 +- server/proxy-call-config.hpp | 63 +++++++++ server/proxy-call-policy.cpp | 71 ++++++++++ server/proxy-call-policy.hpp | 57 ++++++++ tests/unit_tests/server/configs/CMakeLists.txt | 3 + .../system.d/org.tizen.containers.tests.conf | 14 ++ .../ut-containers-manager/buggy-daemon.conf | 3 +- .../buggy-default-daemon.conf | 3 +- .../buggy-foreground-daemon.conf | 3 +- .../configs/ut-containers-manager/test-daemon.conf | 3 +- .../ut-containers-manager/test-dbus-daemon.conf | 8 +- .../server/configs/ut-server/buggy-daemon.conf | 3 +- .../server/configs/ut-server/test-daemon.conf | 3 +- tests/unit_tests/server/test-dbus-definitions.hpp | 55 ++++++++ tests/unit_tests/server/ut-containers-manager.cpp | 148 +++++++++++++++++++++ 27 files changed, 740 insertions(+), 26 deletions(-) create mode 100644 server/proxy-call-config.hpp create mode 100644 server/proxy-call-policy.cpp create mode 100644 server/proxy-call-policy.hpp create mode 100644 tests/unit_tests/server/configs/dbus-1/system.d/org.tizen.containers.tests.conf create mode 100644 tests/unit_tests/server/test-dbus-definitions.hpp diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index 1258c1a..7d7b0a1 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -188,3 +188,4 @@ Unit tests for both: server and client and integration tests. %{script_dir}/sc_test_parser.py %{_datadir}/security-containers %{python_sitelib}/sc_integration_tests +/etc/dbus-1/system.d/org.tizen.containers.tests.conf diff --git a/server/configs/daemon.conf b/server/configs/daemon.conf index 9c0eba6..67ef356 100644 --- a/server/configs/daemon.conf +++ b/server/configs/daemon.conf @@ -8,5 +8,6 @@ "device" : "gpio-keys", "code" : 139, "numberOfEvents" : 3, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/server/container-connection.cpp b/server/container-connection.cpp index adabace..f71a5a6 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -146,6 +146,11 @@ void ContainerConnection::setFileMoveRequestCallback( mFileMoveRequestCallback = callback; } +void ContainerConnection::setProxyCallCallback(const ProxyCallCallback& callback) +{ + mProxyCallCallback = callback; +} + void ContainerConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, @@ -174,6 +179,34 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, mFileMoveRequestCallback(destination, path, result); } } + + if (methodName == api::METHOD_PROXY_CALL) { + const gchar* target = NULL; + const gchar* targetBusName = NULL; + const gchar* targetObjectPath = NULL; + const gchar* targetInterface = NULL; + const gchar* targetMethod = NULL; + GVariant* rawArgs = NULL; + g_variant_get(parameters, + "(&s&s&s&s&sv)", + &target, + &targetBusName, + &targetObjectPath, + &targetInterface, + &targetMethod, + &rawArgs); + dbus::GVariantPtr args(rawArgs, g_variant_unref); + + if (mProxyCallCallback) { + mProxyCallCallback(target, + targetBusName, + targetObjectPath, + targetInterface, + targetMethod, + args.get(), + result); + } + } } void ContainerConnection::onSignalReceived(const std::string& senderBusName, @@ -207,5 +240,21 @@ void ContainerConnection::sendNotification(const std::string& container, parameters); } +void ContainerConnection::proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback) +{ + mDbusConnection->callMethodAsync(busName, + objectPath, + interface, + method, + parameters, + std::string(), + callback); +} + } // namespace security_containers diff --git a/server/container-connection.hpp b/server/container-connection.hpp index 7759a09..a635bc8 100644 --- a/server/container-connection.hpp +++ b/server/container-connection.hpp @@ -55,6 +55,15 @@ public: dbus::MethodResultBuilder::Pointer result )> FileMoveRequestCallback; + typedef std::function ProxyCallCallback; + /** * Register notification request callback */ @@ -71,12 +80,27 @@ public: void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); /** + * Register proxy call callback + */ + void setProxyCallCallback(const ProxyCallCallback& callback); + + /** * Send notification signal to this container */ void sendNotification(const std::string& container, const std::string& application, const std::string& message); + /** + * Make a proxy call + */ + void proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback); + private: dbus::DbusConnection::Pointer mDbusConnection; std::mutex mNameMutex; @@ -87,6 +111,7 @@ private: NotifyActiveContainerCallback mNotifyActiveContainerCallback; DisplayOffCallback mDisplayOffCallback; FileMoveRequestCallback mFileMoveRequestCallback; + ProxyCallCallback mProxyCallCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/container-dbus-definitions.hpp b/server/container-dbus-definitions.hpp index febcbbc..fe72e4d 100644 --- a/server/container-dbus-definitions.hpp +++ b/server/container-dbus-definitions.hpp @@ -38,6 +38,7 @@ const std::string INTERFACE = "org.tizen.containers.doma const std::string METHOD_NOTIFY_ACTIVE_CONTAINER = "NotifyActiveContainer"; const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest"; +const std::string METHOD_PROXY_CALL = "ProxyCall"; const std::string SIGNAL_NOTIFICATION = "Notification"; const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND"; @@ -60,6 +61,15 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " + " " + " " + " " + " " " " " " " " diff --git a/server/container.cpp b/server/container.cpp index 96ca936..0b61d65 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -128,6 +128,9 @@ void Container::start() if (mFileMoveCallback) { mConnection->setFileMoveRequestCallback(mFileMoveCallback); } + if (mProxyCallCallback) { + mConnection->setProxyCallCallback(mProxyCallCallback); + } // Send to the background only after we're connected, // otherwise it'd take ages. @@ -270,5 +273,35 @@ void Container::setFileMoveRequestCallback(const FileMoveRequestCallback& callba } } +void Container::setProxyCallCallback(const ProxyCallCallback& callback) +{ + Lock lock(mReconnectMutex); + + mProxyCallCallback = callback; + if (mConnection) { + mConnection->setProxyCallCallback(callback); + } +} + +void Container::proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback) +{ + Lock lock(mReconnectMutex); + if (mConnection) { + mConnection->proxyCallAsync(busName, + objectPath, + interface, + method, + parameters, + callback); + } else { + LOGE(getId() << ": Can't do a proxy call, no connection to DBUS"); + } +} + } // namespace security_containers diff --git a/server/container.hpp b/server/container.hpp index 4c1c879..dff5d23 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -52,6 +52,7 @@ public: typedef ContainerConnection::NotifyActiveContainerCallback NotifyActiveContainerCallback; typedef ContainerConnection::DisplayOffCallback DisplayOffCallback; typedef ContainerConnection::FileMoveRequestCallback FileMoveRequestCallback; + typedef ContainerConnection::ProxyCallCallback ProxyCallCallback; /** * Returns a vector of regexps defining files permitted to be @@ -144,6 +145,11 @@ public: void setDisplayOffCallback(const DisplayOffCallback& callback); /** + * Register proxy call callback + */ + void setProxyCallCallback(const ProxyCallCallback& callback); + + /** * Send notification signal to this container * * @param container name of container in which the notification occurred @@ -159,6 +165,16 @@ public: */ void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); + /** + * Make a proxy call + */ + void proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback); + private: ContainerConfig mConfig; std::vector mPermittedToSend; @@ -172,6 +188,7 @@ private: NotifyActiveContainerCallback mNotifyCallback; DisplayOffCallback mDisplayOffCallback; FileMoveRequestCallback mFileMoveCallback; + ProxyCallCallback mProxyCallCallback; std::string mRunMountPoint; void onNameLostCallback(); diff --git a/server/containers-manager-config.hpp b/server/containers-manager-config.hpp index 7f5cb9d..310dca3 100644 --- a/server/containers-manager-config.hpp +++ b/server/containers-manager-config.hpp @@ -28,6 +28,7 @@ #include "config/fields.hpp" #include "input-monitor-config.hpp" +#include "proxy-call-config.hpp" #include #include @@ -71,6 +72,11 @@ struct ContainersManagerConfig { */ std::string runMountPointPrefix; + /** + * Proxy call rules. + */ + std::vector proxyCallRules; + CONFIG_REGISTER ( containerConfigs, @@ -78,7 +84,8 @@ struct ContainersManagerConfig { defaultId, containersPath, inputConfig, - runMountPointPrefix + runMountPointPrefix, + proxyCallRules ) }; diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 0150e4a..7bd22b3 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -32,6 +32,7 @@ #include "utils/paths.hpp" #include "log/logger.hpp" #include "config/manager.hpp" +#include "dbus/exception.hpp" #include #include @@ -56,6 +57,11 @@ bool regexMatchVector(const std::string& str, const std::vector& v return false; } +const std::string HOST_ID = "host"; +const std::string DBUS_ERROR_NAME_FORBIDDEN = "org.tizen.containers.Error.Forbidden"; +const std::string DBUS_ERROR_NAME_FORWARDED = "org.tizen.containers.Error.Forwarded"; +const std::string DBUS_ERROR_NAME_UNKNOWN_TARGET = "org.tizen.containers.Error.UnknownTarget"; + } // namespace ContainersManager::ContainersManager(const std::string& managerConfigPath): mDetachOnExit(false) @@ -63,6 +69,12 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet LOGD("Instantiating ContainersManager object..."); config::loadFromFile(managerConfigPath, mConfig); + mProxyCallPolicy.reset(new ProxyCallPolicy(mConfig.proxyCallRules)); + + using namespace std::placeholders; + mHostConnection.setProxyCallCallback(bind(&ContainersManager::handleProxyCall, + this, HOST_ID, _1, _2, _3, _4, _5, _6, _7)); + for (auto& containerConfig : mConfig.containerConfigs) { std::string containerConfigPath; @@ -76,8 +88,11 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet LOGD("Creating Container " << containerConfigPath); std::unique_ptr c(new Container(containerConfigPath, mConfig.runMountPointPrefix)); - std::string id = c->getId(); - using namespace std::placeholders; + const std::string id = c->getId(); + if (id == HOST_ID) { + throw ContainerOperationException("Cannot use reserved container ID"); + } + c->setNotifyActiveContainerCallback(bind(&ContainersManager::notifyActiveContainerHandler, this, id, _1, _2)); @@ -87,6 +102,9 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet c->setFileMoveRequestCallback(std::bind(&ContainersManager::handleContainerMoveFileRequest, this, id, _1, _2, _3)); + c->setProxyCallCallback(bind(&ContainersManager::handleProxyCall, + this, id, _1, _2, _3, _4, _5, _6, _7)); + mContainers.insert(ContainerMap::value_type(id, std::move(c))); } @@ -314,5 +332,64 @@ void ContainersManager::handleContainerMoveFileRequest(const std::string& srcCon } } +void ContainersManager::handleProxyCall(const std::string& caller, + const std::string& target, + const std::string& targetBusName, + const std::string& targetObjectPath, + const std::string& targetInterface, + const std::string& targetMethod, + GVariant* parameters, + dbus::MethodResultBuilder::Pointer result) +{ + if (!mProxyCallPolicy->isProxyCallAllowed(caller, + target, + targetBusName, + targetObjectPath, + targetInterface, + targetMethod)) { + LOGW("Forbidden proxy call; " << caller << " -> " << target << "; " << targetBusName + << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); + result->setError(DBUS_ERROR_NAME_FORBIDDEN, "Proxy call forbidden"); + return; + } + + LOGI("Proxy call; " << caller << " -> " << target << "; " << targetBusName + << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); + + auto asyncResultCallback = [result](dbus::AsyncMethodCallResult& asyncMethodCallResult) { + try { + GVariant* targetResult = asyncMethodCallResult.get(); + result->set(g_variant_new("(v)", targetResult)); + } catch (dbus::DbusException& e) { + result->setError(DBUS_ERROR_NAME_FORWARDED, e.what()); + } + }; + + if (target == HOST_ID) { + mHostConnection.proxyCallAsync(targetBusName, + targetObjectPath, + targetInterface, + targetMethod, + parameters, + asyncResultCallback); + return; + } + + ContainerMap::const_iterator targetIter = mContainers.find(target); + if (targetIter == mContainers.end()) { + LOGE("Target container '" << target << "' not found"); + result->setError(DBUS_ERROR_NAME_UNKNOWN_TARGET, "Unknown proxy call target"); + return; + } + + Container& targetContainer = *targetIter->second; + targetContainer.proxyCallAsync(targetBusName, + targetObjectPath, + targetInterface, + targetMethod, + parameters, + asyncResultCallback); +} + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 1e29ed7..4354fdd 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -30,6 +30,7 @@ #include "containers-manager-config.hpp" #include "host-connection.hpp" #include "input-monitor.hpp" +#include "proxy-call-policy.hpp" #include #include @@ -79,6 +80,7 @@ private: HostConnection mHostConnection; // to hold InputMonitor pointer to monitor if container switching sequence is recognized std::unique_ptr mSwitchingSequenceMonitor; + std::unique_ptr mProxyCallPolicy; typedef std::unordered_map> ContainerMap; ContainerMap mContainers; // map of containers, id is the key bool mDetachOnExit; @@ -92,10 +94,19 @@ private: const std::string& dstContainerId, const std::string& path, dbus::MethodResultBuilder::Pointer result); + void handleProxyCall(const std::string& caller, + const std::string& target, + const std::string& targetBusName, + const std::string& targetObjectPath, + const std::string& targetInterface, + const std::string& targetMethod, + GVariant* parameters, + dbus::MethodResultBuilder::Pointer result); + }; -} +} // namespace security_containers #endif // SERVER_CONTAINERS_MANAGER_HPP diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 4f9a2f2..2821202 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -110,28 +110,65 @@ void HostConnection::onNameLost() } } -void HostConnection::setTestCallback(const TestCallback& callback) +void HostConnection::setProxyCallCallback(const ProxyCallCallback& callback) { - mTestCallback = callback; + mProxyCallCallback = callback; } void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, - GVariant* /*parameters*/, + GVariant* parameters, dbus::MethodResultBuilder::Pointer result) { if (objectPath != hostapi::OBJECT_PATH || interface != hostapi::INTERFACE) { return; } - if (methodName == hostapi::METHOD_TEST) { - if (mTestCallback) { - mTestCallback(); - result->setVoid(); + if (methodName == hostapi::METHOD_PROXY_CALL) { + const gchar* target = NULL; + const gchar* targetBusName = NULL; + const gchar* targetObjectPath = NULL; + const gchar* targetInterface = NULL; + const gchar* targetMethod = NULL; + GVariant* rawArgs = NULL; + g_variant_get(parameters, + "(&s&s&s&s&sv)", + &target, + &targetBusName, + &targetObjectPath, + &targetInterface, + &targetMethod, + &rawArgs); + dbus::GVariantPtr args(rawArgs, g_variant_unref); + + if (mProxyCallCallback) { + mProxyCallCallback(target, + targetBusName, + targetObjectPath, + targetInterface, + targetMethod, + args.get(), + result); } } } +void HostConnection::proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback) +{ + mDbusConnection->callMethodAsync(busName, + objectPath, + interface, + method, + parameters, + std::string(), + callback); +} + } // namespace security_containers diff --git a/server/host-connection.hpp b/server/host-connection.hpp index d78949f..88cb480 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -43,12 +43,28 @@ public: // ------------- API -------------- - typedef std::function TestCallback; + typedef std::function ProxyCallCallback; /** - * Register test callback + * Register proxy call callback */ - void setTestCallback(const TestCallback& callback); + void setProxyCallCallback(const ProxyCallCallback& callback); + + /** + * Make a proxy call + */ + void proxyCallAsync(const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters, + const dbus::DbusConnection::AsyncMethodCallCallback& callback); private: dbus::DbusConnection::Pointer mDbusConnection; @@ -56,7 +72,7 @@ private: std::condition_variable mNameCondition; bool mNameAcquired; bool mNameLost; - TestCallback mTestCallback; + ProxyCallCallback mProxyCallCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 2d82fd3..f41da38 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -34,14 +34,21 @@ namespace hostapi { const std::string BUS_NAME = "org.tizen.containers.host"; const std::string OBJECT_PATH = "/org/tizen/containers/host"; -const std::string INTERFACE = "org.tizen.containers.host.test"; +const std::string INTERFACE = "org.tizen.containers.host.manager"; -const std::string METHOD_TEST = "Test"; +const std::string METHOD_PROXY_CALL = "ProxyCall"; const std::string DEFINITION = "" " " - " " + " " + " " + " " + " " + " " + " " + " " + " " " " " " ""; diff --git a/server/proxy-call-config.hpp b/server/proxy-call-config.hpp new file mode 100644 index 0000000..f20d119 --- /dev/null +++ b/server/proxy-call-config.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Declaration of the struct for storing proxy call configuration + */ + + +#ifndef SERVER_PROXY_CALL_CONFIG_HPP +#define SERVER_PROXY_CALL_CONFIG_HPP + + +#include "config/fields.hpp" + +#include + + +namespace security_containers { + +/** + * A single allow rule for proxy call dispatching. + */ +struct ProxyCallRule { + + std::string caller; ///< caller id (container id or host) + std::string target; ///< target id (container id or host) + std::string targetBusName; ///< target dbus bus name + std::string targetObjectPath; ///< target dbus object path + std::string targetInterface; ///< target dbus interface + std::string targetMethod; ///< target dbus method + + CONFIG_REGISTER + ( + caller, + target, + targetBusName, + targetObjectPath, + targetInterface, + targetMethod + ) + +}; + +} // namespace security_containers + +#endif /* SERVER_PROXY_CALL_CONFIG_HPP */ diff --git a/server/proxy-call-policy.cpp b/server/proxy-call-policy.cpp new file mode 100644 index 0000000..c452d53 --- /dev/null +++ b/server/proxy-call-policy.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Implementation of a class for checking permissions of proxy calls + */ + + +#include "config.hpp" + +#include "proxy-call-policy.hpp" + + +namespace security_containers { + +namespace { +const std::string ANY = "*"; + +inline bool match(const std::string& rule, const std::string& value) { + // simple matching, change to regex if it turns out to be insufficient + return rule == ANY || rule == value; +} + +} // namespace + + +ProxyCallPolicy::ProxyCallPolicy(const std::vector& proxyCallRules) + : mProxyCallRules(proxyCallRules) +{ +} + +bool ProxyCallPolicy::isProxyCallAllowed(const std::string& caller, + const std::string& target, + const std::string& targetBusName, + const std::string& targetObjectPath, + const std::string& targetInterface, + const std::string& targetMethod) +{ + for (const ProxyCallRule& rule : mProxyCallRules) { + if (match(rule.caller, caller) + && match(rule.target, target) + && match(rule.targetBusName, targetBusName) + && match(rule.targetObjectPath, targetObjectPath) + && match(rule.targetInterface, targetInterface) + && match(rule.targetMethod, targetMethod)) { + return true; + } + } + + return false; +} + + +} // namespace security_containers diff --git a/server/proxy-call-policy.hpp b/server/proxy-call-policy.hpp new file mode 100644 index 0000000..cbab0e0 --- /dev/null +++ b/server/proxy-call-policy.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Declaration of a class for checking permissions of proxy calls + */ + + +#ifndef SERVER_PROXY_CALL_POLICY_HPP +#define SERVER_PROXY_CALL_POLICY_HPP + +#include "proxy-call-config.hpp" + +#include + + +namespace security_containers { + + +class ProxyCallPolicy { + +public: + ProxyCallPolicy(const std::vector& proxyCallRules); + + bool isProxyCallAllowed(const std::string& caller, + const std::string& target, + const std::string& targetBusName, + const std::string& targetObjectPath, + const std::string& targetInterface, + const std::string& targetMethod); + +private: + std::vector mProxyCallRules; +}; + + +} // namespace security_containers + + +#endif // SERVER_PROXY_CALL_POLICY_HPP diff --git a/tests/unit_tests/server/configs/CMakeLists.txt b/tests/unit_tests/server/configs/CMakeLists.txt index fac2f9c..816a5bc 100644 --- a/tests/unit_tests/server/configs/CMakeLists.txt +++ b/tests/unit_tests/server/configs/CMakeLists.txt @@ -110,3 +110,6 @@ INSTALL(FILES ${network_admin_CONF} INSTALL(FILES ${connection_CONF} DESTINATION ${SC_TEST_CONFIG_INSTALL_DIR}/server/ut-container-connection) + +INSTALL(FILES dbus-1/system.d/org.tizen.containers.tests.conf + DESTINATION ${SYSCONF_INSTALL_DIR}/dbus-1/system.d/) diff --git a/tests/unit_tests/server/configs/dbus-1/system.d/org.tizen.containers.tests.conf b/tests/unit_tests/server/configs/dbus-1/system.d/org.tizen.containers.tests.conf new file mode 100644 index 0000000..be6c6d6 --- /dev/null +++ b/tests/unit_tests/server/configs/dbus-1/system.d/org.tizen.containers.tests.conf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf index c2d0ca3..92abbe2 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf @@ -8,5 +8,6 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf index 7b380cb..a19268c 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-default-daemon.conf @@ -8,5 +8,6 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf index 8f177ae..bcaba00 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf @@ -8,5 +8,6 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf index c5a42c0..6147c03 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf @@ -8,5 +8,6 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf index f7aedc6..2a6ad35 100644 --- a/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf +++ b/tests/unit_tests/server/configs/ut-containers-manager/test-dbus-daemon.conf @@ -10,5 +10,11 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [{"caller" : "*", + "target" : "*", + "targetBusName" : "org.tizen.containers.tests", + "targetObjectPath" : "*", + "targetInterface" : "*", + "targetMethod" : "*"}] } diff --git a/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf index 9e2298f..cad519c 100644 --- a/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf @@ -8,5 +8,6 @@ "device" : "/dev/doesnotexist", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/configs/ut-server/test-daemon.conf b/tests/unit_tests/server/configs/ut-server/test-daemon.conf index 5c3b373..868f12b 100644 --- a/tests/unit_tests/server/configs/ut-server/test-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/test-daemon.conf @@ -8,5 +8,6 @@ "device" : "gpio-keys.4", "code" : 139, "numberOfEvents" : 2, - "timeWindowMs" : 500} + "timeWindowMs" : 500}, + "proxyCallRules" : [] } diff --git a/tests/unit_tests/server/test-dbus-definitions.hpp b/tests/unit_tests/server/test-dbus-definitions.hpp new file mode 100644 index 0000000..ddad4ac --- /dev/null +++ b/tests/unit_tests/server/test-dbus-definitions.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Piotr Bartosiewicz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @brief Common definitions for dbus tests + */ + +#ifndef UNIT_TESTS_SERVER_TEST_DBUS_DEFINITIONS_HPP +#define UNIT_TESTS_SERVER_TEST_DBUS_DEFINITIONS_HPP + +#include + + +namespace security_containers { +namespace testapi { + + +const std::string BUS_NAME = "org.tizen.containers.tests"; +const std::string OBJECT_PATH = "/org/tizen/containers/tests"; +const std::string INTERFACE = "tests.api"; +const std::string METHOD = "Method"; + +const std::string DEFINITION = + "" + " " + " " + " " + " " + " " + " " + ""; + + +} // namespace testapi +} // namespace security_containers + + +#endif // UNIT_TESTS_SERVER_TEST_DBUS_DEFINITIONS_HPP diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index bf91d9f..64659ef 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -28,6 +28,8 @@ #include "containers-manager.hpp" #include "container-dbus-definitions.hpp" +#include "host-dbus-definitions.hpp" +#include "test-dbus-definitions.hpp" // TODO: Switch to real power-manager dbus defs when they will be implemented in power-manager #include "fake-power-manager-dbus-definitions.hpp" #include "exception.hpp" @@ -73,6 +75,10 @@ const std::string FILE_CONTENT = "File content\n" class DbusAccessory { public: + typedef std::function TestApiMethodCallback; + DbusAccessory(int id) : mId(id), mClient(DbusConnection::create(acquireAddress())), @@ -153,6 +159,65 @@ public: return std::string(retcode); } + void registerTestApiObject(const TestApiMethodCallback& callback) + { + auto handler = [callback](const std::string& objectPath, + const std::string& interface, + const std::string& methodName, + GVariant* parameters, + MethodResultBuilder::Pointer result) { + if (objectPath == testapi::OBJECT_PATH && + interface == testapi::INTERFACE && + methodName == testapi::METHOD) { + const gchar* argument = NULL; + g_variant_get(parameters, "(&s)", &argument); + if (callback) { + callback(argument, result); + } + } + }; + mClient->registerObject(testapi::OBJECT_PATH, testapi::DEFINITION, handler); + } + + std::string testApiProxyCall(const std::string& target, const std::string& argument) + { + GVariant* parameters = g_variant_new("(s)", argument.c_str()); + GVariantPtr result = proxyCall(target, + testapi::BUS_NAME, + testapi::OBJECT_PATH, + testapi::INTERFACE, + testapi::METHOD, + parameters); + const gchar* ret = NULL; + g_variant_get(result.get(), "(&s)", &ret); + return ret; + } + + + GVariantPtr proxyCall(const std::string& target, + const std::string& busName, + const std::string& objectPath, + const std::string& interface, + const std::string& method, + GVariant* parameters) + { + GVariant* packedParameters = g_variant_new("(sssssv)", + target.c_str(), + busName.c_str(), + objectPath.c_str(), + interface.c_str(), + method.c_str(), + parameters); + GVariantPtr result = mClient->callMethod(isHost() ? hostapi::BUS_NAME : api::BUS_NAME, + isHost() ? hostapi::OBJECT_PATH : api::OBJECT_PATH, + isHost() ? hostapi::INTERFACE : api::INTERFACE, + isHost() ? hostapi::METHOD_PROXY_CALL : api::METHOD_PROXY_CALL, + packedParameters, + "(v)"); + GVariant* unpackedResult = NULL; + g_variant_get(result.get(), "(v)", &unpackedResult); + return GVariantPtr(unpackedResult, g_variant_unref); + } private: const int mId; DbusConnection::Pointer mClient; @@ -161,13 +226,25 @@ private: std::mutex mMutex; std::condition_variable mNameCondition; + bool isHost() const { + return mId == 0; + } + std::string acquireAddress() const { + if (isHost()) { + return "unix:path=/var/run/dbus/system_bus_socket"; + } return "unix:path=/tmp/ut-containers-manager/console" + std::to_string(mId) + "-dbus/dbus/system_bus_socket"; } }; +std::function expectedMessage(const std::string& message) { + return [=](const std::exception& e) { + return e.what() == message; + }; +} struct Fixture { utils::ScopedGlibLoop mLoop; @@ -496,5 +573,76 @@ BOOST_AUTO_TEST_CASE(AllowSwitchToDefaultTest) } } +BOOST_AUTO_TEST_CASE(ProxyCallTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + cm.startAll(); + + std::map> dbuses; + for (int i = 0; i <= TEST_DBUS_CONNECTION_CONTAINERS_COUNT; ++i) { + dbuses[i] = std::unique_ptr(new DbusAccessory(i)); + } + + for (auto& dbus : dbuses) { + dbus.second->setName(testapi::BUS_NAME); + + const int id = dbus.first; + auto handler = [id](const std::string& argument, MethodResultBuilder::Pointer result) { + if (argument.empty()) { + result->setError("org.tizen.containers.Error.Test", "Test error"); + } else { + std::string ret = "reply from " + std::to_string(id) + ": " + argument; + result->set(g_variant_new("(s)", ret.c_str())); + } + }; + dbus.second->registerTestApiObject(handler); + } + + // host -> container2 + BOOST_CHECK_EQUAL("reply from 2: param1", + dbuses.at(0)->testApiProxyCall("ut-containers-manager-console2-dbus", + "param1")); + + // host -> host + BOOST_CHECK_EQUAL("reply from 0: param2", + dbuses.at(0)->testApiProxyCall("host", + "param2")); + + // container1 -> host + BOOST_CHECK_EQUAL("reply from 0: param3", + dbuses.at(1)->testApiProxyCall("host", + "param3")); + + // container1 -> container2 + BOOST_CHECK_EQUAL("reply from 2: param4", + dbuses.at(1)->testApiProxyCall("ut-containers-manager-console2-dbus", + "param4")); + + // container2 -> container2 + BOOST_CHECK_EQUAL("reply from 2: param5", + dbuses.at(2)->testApiProxyCall("ut-containers-manager-console2-dbus", + "param5")); + + // host -> unknown + BOOST_CHECK_EXCEPTION(dbuses.at(0)->testApiProxyCall("unknown", "param"), + DbusCustomException, + expectedMessage("Unknown proxy call target")); + + // forwarding error + BOOST_CHECK_EXCEPTION(dbuses.at(0)->testApiProxyCall("host", ""), + DbusCustomException, + expectedMessage("Test error")); + + // forbidden call + BOOST_CHECK_EXCEPTION(dbuses.at(0)->proxyCall("host", + "org.fake", + "/a/b", + "c.d", + "foo", + g_variant_new("(s)", "arg")), + DbusCustomException, + expectedMessage("Proxy call forbidden")); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 014f4e74208a68f9edae11e0b3f58c1f1ac794e0 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Wed, 23 Jul 2014 16:18:43 +0200 Subject: [PATCH 08/16] Release version 0.1.1 Change-Id: I0fdb371060d86446141700c60958d165cbf44d88 --- packaging/security-containers.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index 7d7b0a1..f6a77e1 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -7,7 +7,7 @@ %define input_event_group video Name: security-containers -Version: 0.1.0 +Version: 0.1.1 Release: 0 Source0: %{name}-%{version}.tar.gz License: Apache-2.0 @@ -16,7 +16,7 @@ Summary: Daemon for managing containers BuildRequires: cmake BuildRequires: boost-devel BuildRequires: libvirt-devel -BuildRequires: libjson-devel +BuildRequires: libjson-devel >= 0.10.0 BuildRequires: libcap-ng-devel BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libsystemd-journal) -- 2.7.4 From e785e1bbacccf70374ab14cda57b7059d07cdbff Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Thu, 24 Jul 2014 10:22:03 +0200 Subject: [PATCH 09/16] Fix dependency problem in spec [Bug/Feature] Build break [Cause] Dependency version not match [Solution] N/A [Verification] Build with gbs Change-Id: I0b1a93d293364edea18b15b58cb61fa998674960 --- packaging/security-containers.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index f6a77e1..e639a98 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -16,7 +16,7 @@ Summary: Daemon for managing containers BuildRequires: cmake BuildRequires: boost-devel BuildRequires: libvirt-devel -BuildRequires: libjson-devel >= 0.10.0 +BuildRequires: libjson-devel >= 0.10 BuildRequires: libcap-ng-devel BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libsystemd-journal) -- 2.7.4 From e9617fa11ae5172e3b2cb9338fdcd23476a291be Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Wed, 23 Jul 2014 12:56:47 +0200 Subject: [PATCH 10/16] Dbus API for sharing containers DBuses [Bug/Feature] New method on host dbus interface for getting list of containers dbus addresses and new signals when containers dbus become available or unavailable. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Ib37d47c8e2ffbdca58828c542d7b474e068ca138 --- server/container.cpp | 61 +++++++++--- server/container.hpp | 16 ++++ server/containers-manager.cpp | 25 +++++ server/containers-manager.hpp | 3 + server/host-connection.cpp | 23 +++++ server/host-connection.hpp | 17 +++- server/host-dbus-definitions.hpp | 10 ++ tests/unit_tests/server/ut-containers-manager.cpp | 108 +++++++++++++++++++++- 8 files changed, 246 insertions(+), 17 deletions(-) diff --git a/server/container.cpp b/server/container.cpp index 0b61d65..4284fec 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -82,7 +82,7 @@ Container::~Container() // condition on the mReconnectThread. { Lock lock(mReconnectMutex); - mConnection.reset(); + disconnect(); } if (mReconnectThread.joinable()) { @@ -117,7 +117,28 @@ void Container::start() mConnectionTransport.reset(new ContainerConnectionTransport(mRunMountPoint)); mNetworkAdmin->start(); mAdmin->start(); - mConnection.reset(new ContainerConnection(mConnectionTransport->acquireAddress(), + connect(); + + // Send to the background only after we're connected, + // otherwise it'd take ages. + LOGD(getId() << ": DBUS connected, sending to the background"); + goBackground(); +} + +void Container::stop() +{ + Lock lock(mReconnectMutex); + disconnect(); + mAdmin->stop(); + mNetworkAdmin->stop(); + mConnectionTransport.reset(); +} + +void Container::connect() +{ + // assume called under reconnect lock + mDbusAddress = mConnectionTransport->acquireAddress(); + mConnection.reset(new ContainerConnection(mDbusAddress, std::bind(&Container::onNameLostCallback, this))); if (mNotifyCallback) { mConnection->setNotifyActiveContainerCallback(mNotifyCallback); @@ -131,20 +152,28 @@ void Container::start() if (mProxyCallCallback) { mConnection->setProxyCallCallback(mProxyCallCallback); } + if (mDbusStateChangedCallback) { + mDbusStateChangedCallback(mDbusAddress); + } +} - // Send to the background only after we're connected, - // otherwise it'd take ages. - LOGD(getId() << ": DBUS connected, sending to the background"); - goBackground(); +void Container::disconnect() +{ + // assume called under reconnect lock + if (mConnection) { + mConnection.reset(); + mDbusAddress.clear(); + if (mDbusStateChangedCallback) { + // notify about invalid dbusAddress for this container + mDbusStateChangedCallback(std::string()); + } + } } -void Container::stop() +std::string Container::getDbusAddress() { Lock lock(mReconnectMutex); - mConnection.reset(); - mAdmin->stop(); - mNetworkAdmin->stop(); - mConnectionTransport.reset(); + return mDbusAddress; } void Container::goForeground() @@ -204,7 +233,7 @@ void Container::reconnectHandler() { { Lock lock(mReconnectMutex); - mConnection.reset(); + disconnect(); } for (int i = 0; i < RECONNECT_RETRIES; ++i) { @@ -219,8 +248,7 @@ void Container::reconnectHandler() try { LOGT(getId() << ": Reconnect try " << i + 1); - mConnection.reset(new ContainerConnection(mConnectionTransport->acquireAddress(), - std::bind(&Container::onNameLostCallback, this))); + connect(); LOGI(getId() << ": Reconnected"); return; } catch (SecurityContainersException&) { @@ -283,6 +311,11 @@ void Container::setProxyCallCallback(const ProxyCallCallback& callback) } } +void Container::setDbusStateChangedCallback(const DbusStateChangedCallback& callback) +{ + mDbusStateChangedCallback = callback; +} + void Container::proxyCallAsync(const std::string& busName, const std::string& objectPath, const std::string& interface, diff --git a/server/container.hpp b/server/container.hpp index dff5d23..c29b860 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -54,6 +54,8 @@ public: typedef ContainerConnection::FileMoveRequestCallback FileMoveRequestCallback; typedef ContainerConnection::ProxyCallCallback ProxyCallCallback; + typedef std::function DbusStateChangedCallback; + /** * Returns a vector of regexps defining files permitted to be * send to other containers using file move functionality @@ -166,6 +168,11 @@ public: void setFileMoveRequestCallback(const FileMoveRequestCallback& callback); /** + * Register dbus state changed callback + */ + void setDbusStateChangedCallback(const DbusStateChangedCallback& callback); + + /** * Make a proxy call */ void proxyCallAsync(const std::string& busName, @@ -175,6 +182,11 @@ public: GVariant* parameters, const dbus::DbusConnection::AsyncMethodCallCallback& callback); + /** + * Get a dbus address + */ + std::string getDbusAddress(); + private: ContainerConfig mConfig; std::vector mPermittedToSend; @@ -189,10 +201,14 @@ private: DisplayOffCallback mDisplayOffCallback; FileMoveRequestCallback mFileMoveCallback; ProxyCallCallback mProxyCallCallback; + DbusStateChangedCallback mDbusStateChangedCallback; + std::string mDbusAddress; std::string mRunMountPoint; void onNameLostCallback(); void reconnectHandler(); + void connect(); + void disconnect(); }; diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 7bd22b3..dc6e637 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -75,6 +75,9 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet mHostConnection.setProxyCallCallback(bind(&ContainersManager::handleProxyCall, this, HOST_ID, _1, _2, _3, _4, _5, _6, _7)); + mHostConnection.setGetContainerDbusesCallback(bind( + &ContainersManager::handleGetContainerDbuses, this, _1)); + for (auto& containerConfig : mConfig.containerConfigs) { std::string containerConfigPath; @@ -105,6 +108,9 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet c->setProxyCallCallback(bind(&ContainersManager::handleProxyCall, this, id, _1, _2, _3, _4, _5, _6, _7)); + c->setDbusStateChangedCallback(bind(&ContainersManager::handleDbusStateChanged, + this, id, _1)); + mContainers.insert(ContainerMap::value_type(id, std::move(c))); } @@ -391,5 +397,24 @@ void ContainersManager::handleProxyCall(const std::string& caller, asyncResultCallback); } +void ContainersManager::handleGetContainerDbuses(dbus::MethodResultBuilder::Pointer result) +{ + std::vector entries; + for (auto& container : mContainers) { + GVariant* containerId = g_variant_new_string(container.first.c_str()); + GVariant* dbusAddress = g_variant_new_string(container.second->getDbusAddress().c_str()); + GVariant* entry = g_variant_new_dict_entry(containerId, dbusAddress); + entries.push_back(entry); + } + GVariant* dict = g_variant_new_array(G_VARIANT_TYPE("{ss}"), entries.data(), entries.size()); + result->set(g_variant_new("(*)", dict)); +} + +void ContainersManager::handleDbusStateChanged(const std::string& containerId, + const std::string& dbusAddress) +{ + mHostConnection.signalContainerDbusState(containerId, dbusAddress); +} + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 4354fdd..8a5c823 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -103,6 +103,9 @@ private: GVariant* parameters, dbus::MethodResultBuilder::Pointer result); + void handleGetContainerDbuses(dbus::MethodResultBuilder::Pointer result); + void handleDbusStateChanged(const std::string& containerId, const std::string& dbusAddress); + }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 2821202..88ce5a4 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -115,6 +115,11 @@ void HostConnection::setProxyCallCallback(const ProxyCallCallback& callback) mProxyCallCallback = callback; } +void HostConnection::setGetContainerDbusesCallback(const GetContainerDbusesCallback& callback) +{ + mGetContainerDbusesCallback = callback; +} + void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, @@ -125,6 +130,13 @@ void HostConnection::onMessageCall(const std::string& objectPath, return; } + if (methodName == hostapi::METHOD_GET_CONTAINER_DBUSES) { + if (mGetContainerDbusesCallback) { + mGetContainerDbusesCallback(result); + } + return; + } + if (methodName == hostapi::METHOD_PROXY_CALL) { const gchar* target = NULL; const gchar* targetBusName = NULL; @@ -151,6 +163,7 @@ void HostConnection::onMessageCall(const std::string& objectPath, args.get(), result); } + return; } } @@ -170,5 +183,15 @@ void HostConnection::proxyCallAsync(const std::string& busName, callback); } +void HostConnection::signalContainerDbusState(const std::string& containerId, + const std::string& dbusAddress) +{ + GVariant* parameters = g_variant_new("(ss)", containerId.c_str(), dbusAddress.c_str()); + mDbusConnection->emitSignal(hostapi::OBJECT_PATH, + hostapi::INTERFACE, + hostapi::SIGNAL_CONTAINER_DBUS_STATE, + parameters); +} + } // namespace security_containers diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 88cb480..3d9c493 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -49,7 +49,11 @@ public: const std::string& targetInterface, const std::string& targetMethod, GVariant* parameters, - dbus::MethodResultBuilder::Pointer result)> ProxyCallCallback; + dbus::MethodResultBuilder::Pointer result + )> ProxyCallCallback; + + typedef std::function GetContainerDbusesCallback; /** * Register proxy call callback @@ -57,6 +61,16 @@ public: void setProxyCallCallback(const ProxyCallCallback& callback); /** + * Register get container dbuses callback + */ + void setGetContainerDbusesCallback(const GetContainerDbusesCallback& callback); + + /** + * Send signal describing dbus address state change + */ + void signalContainerDbusState(const std::string& containerId, const std::string& dbusAddress); + + /** * Make a proxy call */ void proxyCallAsync(const std::string& busName, @@ -73,6 +87,7 @@ private: bool mNameAcquired; bool mNameLost; ProxyCallCallback mProxyCallCallback; + GetContainerDbusesCallback mGetContainerDbusesCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index f41da38..4594433 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -37,6 +37,9 @@ const std::string OBJECT_PATH = "/org/tizen/containers/hos const std::string INTERFACE = "org.tizen.containers.host.manager"; const std::string METHOD_PROXY_CALL = "ProxyCall"; +const std::string METHOD_GET_CONTAINER_DBUSES = "GetContainerDbuses"; + +const std::string SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState"; const std::string DEFINITION = "" @@ -50,6 +53,13 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " + " " + " " " " ""; diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index 64659ef..43bc15a 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -75,10 +75,14 @@ const std::string FILE_CONTENT = "File content\n" class DbusAccessory { public: + static const int HOST_ID = 0; + typedef std::function TestApiMethodCallback; + typedef std::map Dbuses; + DbusAccessory(int id) : mId(id), mClient(DbusConnection::create(acquireAddress())), @@ -122,7 +126,7 @@ public: void signalSubscribe(const DbusConnection::SignalCallback& callback) { - mClient->signalSubscribe(callback, api::BUS_NAME); + mClient->signalSubscribe(callback, isHost() ? hostapi::BUS_NAME : api::BUS_NAME); } void emitSignal(const std::string& objectPath, @@ -218,6 +222,28 @@ public: g_variant_get(result.get(), "(v)", &unpackedResult); return GVariantPtr(unpackedResult, g_variant_unref); } + + Dbuses callMethodGetContainerDbuses() { + assert(isHost()); + Dbuses dbuses; + GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, + hostapi::OBJECT_PATH, + hostapi::INTERFACE, + hostapi::METHOD_GET_CONTAINER_DBUSES, + NULL, + "(a{ss})"); + GVariant* array = NULL; + g_variant_get(result.get(), "(*)", &array); + dbus::GVariantPtr autounref(array, g_variant_unref); + size_t count = g_variant_n_children(array); + for (size_t n = 0; n < count; ++n) { + const char* containerId = NULL; + const char* dbusAddress = NULL; + g_variant_get_child(array, n, "{&s&s}", &containerId, &dbusAddress); + dbuses.insert(Dbuses::value_type(containerId, dbusAddress)); + } + return dbuses; + } private: const int mId; DbusConnection::Pointer mClient; @@ -227,7 +253,7 @@ private: std::condition_variable mNameCondition; bool isHost() const { - return mId == 0; + return mId == HOST_ID; } std::string acquireAddress() const @@ -644,5 +670,83 @@ BOOST_AUTO_TEST_CASE(ProxyCallTest) expectedMessage("Proxy call forbidden")); } +namespace { + const DbusAccessory::Dbuses EXPECTED_DBUSES_STOPPED = { + {"ut-containers-manager-console1-dbus", ""}, + {"ut-containers-manager-console2-dbus", ""}, + {"ut-containers-manager-console3-dbus", ""}}; + + const DbusAccessory::Dbuses EXPECTED_DBUSES_STARTED = { + {"ut-containers-manager-console1-dbus", + "unix:path=/tmp/ut-containers-manager/console1-dbus/dbus/system_bus_socket"}, + {"ut-containers-manager-console2-dbus", + "unix:path=/tmp/ut-containers-manager/console2-dbus/dbus/system_bus_socket"}, + {"ut-containers-manager-console3-dbus", + "unix:path=/tmp/ut-containers-manager/console3-dbus/dbus/system_bus_socket"}}; +} // namespace + +BOOST_AUTO_TEST_CASE(GetContainerDbusesTest) +{ + DbusAccessory host(DbusAccessory::HOST_ID); + + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + + BOOST_CHECK(EXPECTED_DBUSES_STOPPED == host.callMethodGetContainerDbuses()); + + cm.startAll(); + + BOOST_CHECK(EXPECTED_DBUSES_STARTED == host.callMethodGetContainerDbuses()); + + cm.stopAll(); + + BOOST_CHECK(EXPECTED_DBUSES_STOPPED == host.callMethodGetContainerDbuses()); +} + +BOOST_AUTO_TEST_CASE(ContainerDbusesSignalsTest) +{ + DbusAccessory host(DbusAccessory::HOST_ID); + + Latch signalLatch; + DbusAccessory::Dbuses collectedDbuses; + + auto onSignal = [&] (const std::string& /*senderBusName*/, + const std::string& objectPath, + const std::string& interface, + const std::string& signalName, + GVariant* parameters) { + if (objectPath == hostapi::OBJECT_PATH && + interface == hostapi::INTERFACE && + signalName == hostapi::SIGNAL_CONTAINER_DBUS_STATE) { + + const gchar* containerId = NULL; + const gchar* dbusAddress = NULL; + g_variant_get(parameters, "(&s&s)", &containerId, &dbusAddress); + + collectedDbuses.insert(DbusAccessory::Dbuses::value_type(containerId, dbusAddress)); + signalLatch.set(); + } + }; + + host.signalSubscribe(onSignal); + + { + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + + BOOST_CHECK(signalLatch.empty()); + BOOST_CHECK(collectedDbuses.empty()); + + cm.startAll(); + + BOOST_CHECK(signalLatch.waitForN(TEST_DBUS_CONNECTION_CONTAINERS_COUNT, EVENT_TIMEOUT)); + BOOST_CHECK(signalLatch.empty()); + BOOST_CHECK(EXPECTED_DBUSES_STARTED == collectedDbuses); + collectedDbuses.clear(); + } + + BOOST_CHECK(signalLatch.waitForN(TEST_DBUS_CONNECTION_CONTAINERS_COUNT, EVENT_TIMEOUT)); + BOOST_CHECK(signalLatch.empty()); + BOOST_CHECK(EXPECTED_DBUSES_STOPPED == collectedDbuses); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From a5c612deb7685dae1fd5aececd81db28d159dd4e Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 22 Jul 2014 17:25:20 +0200 Subject: [PATCH 11/16] API for obtaining container's IDs [Bug/Feature] D-Bus API for getting the ID of the active container D-Bus API for getting the IDs of all containers [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I03081e3dc5e275f9c0d5c6b5a6cacfef38c5adff --- server/containers-manager.cpp | 28 ++++++++ server/containers-manager.hpp | 2 + server/host-connection.cpp | 31 +++++++-- server/host-connection.hpp | 16 +++++ server/host-dbus-definitions.hpp | 8 +++ tests/unit_tests/server/ut-containers-manager.cpp | 80 ++++++++++++++++++++++- 6 files changed, 158 insertions(+), 7 deletions(-) diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index dc6e637..b2c4222 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -78,6 +78,12 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet mHostConnection.setGetContainerDbusesCallback(bind( &ContainersManager::handleGetContainerDbuses, this, _1)); + mHostConnection.setGetContainerIdsCallback(bind(&ContainersManager::handleGetContainerIdsCall, + this, _1)); + + mHostConnection.setGetActiveContainerIdCallback(bind(&ContainersManager::handleGetActiveContainerIdCall, + this, _1)); + for (auto& containerConfig : mConfig.containerConfigs) { std::string containerConfigPath; @@ -416,5 +422,27 @@ void ContainersManager::handleDbusStateChanged(const std::string& containerId, mHostConnection.signalContainerDbusState(containerId, dbusAddress); } +void ContainersManager::handleGetContainerIdsCall(dbus::MethodResultBuilder::Pointer result) +{ + std::vector containerIds; + for(auto& container: mContainers){ + containerIds.push_back(g_variant_new_string(container.first.c_str())); + } + + GVariant* array = g_variant_new_array(G_VARIANT_TYPE("s"), + containerIds.data(), + containerIds.size()); + result->set(g_variant_new("(*)", array)); +} + +void ContainersManager::handleGetActiveContainerIdCall(dbus::MethodResultBuilder::Pointer result) +{ + LOGI("GetActiveContainerId call"); + if (mContainers[mConfig.foregroundId]->isRunning()){ + result->set(g_variant_new("(s)", mConfig.foregroundId.c_str())); + } else { + result->set(g_variant_new("(s)", "")); + } +} } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 8a5c823..b685028 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -105,6 +105,8 @@ private: void handleGetContainerDbuses(dbus::MethodResultBuilder::Pointer result); void handleDbusStateChanged(const std::string& containerId, const std::string& dbusAddress); + void handleGetContainerIdsCall(dbus::MethodResultBuilder::Pointer result); + void handleGetActiveContainerIdCall(dbus::MethodResultBuilder::Pointer result); }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 88ce5a4..0d96039 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -65,12 +65,7 @@ HostConnection::HostConnection() mDbusConnection->registerObject(hostapi::OBJECT_PATH, hostapi::DEFINITION, std::bind(&HostConnection::onMessageCall, - this, - _1, - _2, - _3, - _4, - _5)); + this, _1, _2, _3, _4, _5)); LOGD("Connected"); } @@ -120,6 +115,16 @@ void HostConnection::setGetContainerDbusesCallback(const GetContainerDbusesCallb mGetContainerDbusesCallback = callback; } +void HostConnection::setGetContainerIdsCallback(const GetContainerIdsCallback& callback) +{ + mGetContainerIdsCallback = callback; +} + +void HostConnection::setGetActiveContainerIdCallback(const GetActiveContainerIdCallback& callback) +{ + mGetActiveContainerIdCallback = callback; +} + void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, @@ -165,6 +170,20 @@ void HostConnection::onMessageCall(const std::string& objectPath, } return; } + + if (methodName == hostapi::METHOD_GET_CONTAINER_ID_LIST){ + if (mGetContainerIdsCallback){ + mGetContainerIdsCallback(result); + } + return; + } + + if (methodName == hostapi::METHOD_GET_ACTIVE_CONTAINER_ID){ + if (mGetActiveContainerIdCallback){ + mGetActiveContainerIdCallback(result); + } + return; + } } void HostConnection::proxyCallAsync(const std::string& busName, diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 3d9c493..962fbb9 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -54,6 +54,10 @@ public: typedef std::function GetContainerDbusesCallback; + typedef std::function GetContainerIdsCallback; + typedef std::function GetActiveContainerIdCallback; + /** * Register proxy call callback @@ -71,6 +75,16 @@ public: void signalContainerDbusState(const std::string& containerId, const std::string& dbusAddress); /** + * Register a callback called to get a list of domain ids + */ + void setGetContainerIdsCallback(const GetContainerIdsCallback& callback); + + /** + * Register a callback called to get the active container id + */ + void setGetActiveContainerIdCallback(const GetContainerIdsCallback& callback); + + /** * Make a proxy call */ void proxyCallAsync(const std::string& busName, @@ -88,6 +102,8 @@ private: bool mNameLost; ProxyCallCallback mProxyCallCallback; GetContainerDbusesCallback mGetContainerDbusesCallback; + GetContainerIdsCallback mGetContainerIdsCallback; + GetActiveContainerIdCallback mGetActiveContainerIdCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index 4594433..ef30e1a 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -38,6 +38,8 @@ const std::string INTERFACE = "org.tizen.containers.host const std::string METHOD_PROXY_CALL = "ProxyCall"; 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 SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState"; @@ -56,6 +58,12 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " + " " " " " " " " diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index 43bc15a..d4708e3 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -223,7 +223,8 @@ public: return GVariantPtr(unpackedResult, g_variant_unref); } - Dbuses callMethodGetContainerDbuses() { + Dbuses callMethodGetContainerDbuses() + { assert(isHost()); Dbuses dbuses; GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, @@ -244,6 +245,47 @@ public: } return dbuses; } + + std::vector callMethodGetContainerIds() + { + assert(isHost()); + GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, + hostapi::OBJECT_PATH, + hostapi::INTERFACE, + hostapi::METHOD_GET_CONTAINER_ID_LIST, + NULL, + "(as)"); + + GVariant* array = NULL; + g_variant_get(result.get(), "(*)", &array); + + size_t arraySize = g_variant_n_children(array); + std::vector containerIds; + for (size_t i = 0; i < arraySize; ++i) { + const char* id = NULL; + g_variant_get_child(array, i, "&s", &id); + containerIds.push_back(id); + } + + g_variant_unref(array); + return containerIds; + } + + std::string callMethodGetActiveContainerId() + { + assert(isHost()); + GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, + hostapi::OBJECT_PATH, + hostapi::INTERFACE, + hostapi::METHOD_GET_ACTIVE_CONTAINER_ID, + NULL, + "(s)"); + + const char* containerId = NULL; + g_variant_get(result.get(), "(&s)", &containerId); + return containerId; + } + private: const int mId; DbusConnection::Pointer mClient; @@ -749,4 +791,40 @@ BOOST_AUTO_TEST_CASE(ContainerDbusesSignalsTest) } +BOOST_AUTO_TEST_CASE(GetContainerIdsTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + + DbusAccessory dbus(DbusAccessory::HOST_ID); + + std::vector containerIds = {"ut-containers-manager-console1-dbus", + "ut-containers-manager-console2-dbus", + "ut-containers-manager-console3-dbus"}; + std::vector returnedIds = dbus.callMethodGetContainerIds(); + + BOOST_CHECK(std::is_permutation(returnedIds.begin(), + returnedIds.end(), + containerIds.begin())); +} + +BOOST_AUTO_TEST_CASE(GetActiveContainerIdTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + cm.startAll(); + + DbusAccessory dbus(DbusAccessory::HOST_ID); + + std::vector containerIds = {"ut-containers-manager-console1-dbus", + "ut-containers-manager-console2-dbus", + "ut-containers-manager-console3-dbus"}; + + for (std::string& containerId: containerIds){ + cm.focus(containerId); + BOOST_CHECK(dbus.callMethodGetActiveContainerId() == containerId); + } + + cm.stopAll(); + BOOST_CHECK(dbus.callMethodGetActiveContainerId() == ""); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From d880b2a8fda680e6970d2916f06c19b19ac1fed4 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Mon, 28 Jul 2014 11:06:13 +0200 Subject: [PATCH 12/16] Fix invalid use of glib loop in unit tests [Bug/Feature] Memleak in unit tests [Cause] Glib loop was started twice [Solution] N/A [Verification] Build, install, run tests under valgrind Change-Id: I7407a0211e141143b3828cf1784f3a2a5ac3f5b3 --- server/container-admin.hpp | 1 - tests/unit_tests/server/ut-input-monitor.cpp | 15 ++++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/server/container-admin.hpp b/server/container-admin.hpp index a1e0baf..3831a3a 100644 --- a/server/container-admin.hpp +++ b/server/container-admin.hpp @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/tests/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp index a0bd9dd..13f1d51 100644 --- a/tests/unit_tests/server/ut-input-monitor.cpp +++ b/tests/unit_tests/server/ut-input-monitor.cpp @@ -40,7 +40,6 @@ #include #include -#include #include #include #include @@ -114,9 +113,8 @@ BOOST_AUTO_TEST_CASE(Config_deviceFilePathNotExisting) InputMonitorException); } -void sendNEvents(unsigned int noOfEventsToSend) +void sendNEvents(Fixture& f, unsigned int noOfEventsToSend) { - Fixture f; Latch eventLatch; std::unique_ptr inputMonitor; @@ -150,17 +148,16 @@ void sendNEvents(unsigned int noOfEventsToSend) BOOST_AUTO_TEST_CASE(Event_oneAtATime) { - sendNEvents(1); + sendNEvents(*this, 1); } BOOST_AUTO_TEST_CASE(Event_tenAtATime) { - sendNEvents(10); + sendNEvents(*this, 10); } -void sendNEventsWithPauses(unsigned int noOfEventsToSend) +void sendNEventsWithPauses(Fixture& f, unsigned int noOfEventsToSend) { - Fixture f; Latch eventLatch; std::unique_ptr inputMonitor; @@ -199,12 +196,12 @@ void sendNEventsWithPauses(unsigned int noOfEventsToSend) BOOST_AUTO_TEST_CASE(Event_oneAtATimeWithPauses) { - sendNEventsWithPauses(1); + sendNEventsWithPauses(*this, 1); } BOOST_AUTO_TEST_CASE(Event_tenAtATimeWithPauses) { - sendNEventsWithPauses(10); + sendNEventsWithPauses(*this, 10); } -- 2.7.4 From 35339dc228673f4454360b9107718078aa8d0c10 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Fri, 25 Jul 2014 10:42:26 +0200 Subject: [PATCH 13/16] Setting the active container through D-Bus [Bug/Feature] D-Bus API for setting the active container [Cause] N/A [Solution] Added the new API Added a common part of dbus definitions [Verification] Build, install, run tests Change-Id: I4be877c17751b6334e8d424ff64de8d884699ede --- server/common-dbus-definitions.hpp | 43 +++++++ server/container-connection.cpp | 22 ++-- server/container-dbus-definitions.hpp | 7 +- server/containers-manager.cpp | 55 ++++++--- server/containers-manager.hpp | 3 +- server/host-connection.cpp | 41 ++++--- server/host-connection.hpp | 14 ++- server/host-dbus-definitions.hpp | 30 +++-- .../unit_tests/server/ut-container-connection.cpp | 17 +-- tests/unit_tests/server/ut-containers-manager.cpp | 123 ++++++++++++++------- 10 files changed, 244 insertions(+), 111 deletions(-) create mode 100644 server/common-dbus-definitions.hpp diff --git a/server/common-dbus-definitions.hpp b/server/common-dbus-definitions.hpp new file mode 100644 index 0000000..8821b34 --- /dev/null +++ b/server/common-dbus-definitions.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Common dbus api definitions + */ + +#ifndef SERVER_COMMON_DBUS_DEFINITIONS_HPP +#define SERVER_COMMON_DBUS_DEFINITIONS_HPP + +#include + + +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 METHOD_PROXY_CALL = "ProxyCall"; + +} // namespace api +} // namespace security_containers + + +#endif // SERVER_COMMON_DBUS_DEFINITIONS_HPP diff --git a/server/container-connection.cpp b/server/container-connection.cpp index f71a5a6..0e96bb2 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -59,19 +59,19 @@ ContainerConnection::ContainerConnection(const std::string& address, const OnNam mDbusConnection = dbus::DbusConnection::create(address); LOGT("Setting DBUS name"); - mDbusConnection->setName(api::BUS_NAME, + mDbusConnection->setName(api::container::BUS_NAME, std::bind(&ContainerConnection::onNameAcquired, this), std::bind(&ContainerConnection::onNameLost, this)); if (!waitForNameAndSetCallback(NAME_ACQUIRED_TIMEOUT, callback)) { - LOGE("Could not acquire dbus name: " << api::BUS_NAME); - throw ContainerConnectionException("Could not acquire dbus name: " + api::BUS_NAME); + LOGE("Could not acquire dbus name: " << api::container::BUS_NAME); + throw ContainerConnectionException("Could not acquire dbus name: " + api::container::BUS_NAME); } LOGT("Registering DBUS interface"); using namespace std::placeholders; - mDbusConnection->registerObject(api::OBJECT_PATH, - api::DEFINITION, + mDbusConnection->registerObject(api::container::OBJECT_PATH, + api::container::DEFINITION, std::bind(&ContainerConnection::onMessageCall, this, _1, @@ -157,11 +157,11 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, GVariant* parameters, dbus::MethodResultBuilder::Pointer result) { - if (objectPath != api::OBJECT_PATH || interface != api::INTERFACE) { + if (objectPath != api::container::OBJECT_PATH || interface != api::container::INTERFACE) { return; } - if (methodName == api::METHOD_NOTIFY_ACTIVE_CONTAINER) { + if (methodName == api::container::METHOD_NOTIFY_ACTIVE_CONTAINER) { const gchar* application = NULL; const gchar* message = NULL; g_variant_get(parameters, "(&s&s)", &application, &message); @@ -171,7 +171,7 @@ void ContainerConnection::onMessageCall(const std::string& objectPath, } } - if (methodName == api::METHOD_FILE_MOVE_REQUEST) { + if (methodName == api::container::METHOD_FILE_MOVE_REQUEST) { const gchar* destination = NULL; const gchar* path = NULL; g_variant_get(parameters, "(&s&s)", &destination, &path); @@ -234,9 +234,9 @@ void ContainerConnection::sendNotification(const std::string& container, container.c_str(), application.c_str(), message.c_str()); - mDbusConnection->emitSignal(api::OBJECT_PATH, - api::INTERFACE, - api::SIGNAL_NOTIFICATION, + mDbusConnection->emitSignal(api::container::OBJECT_PATH, + api::container::INTERFACE, + api::container::SIGNAL_NOTIFICATION, parameters); } diff --git a/server/container-dbus-definitions.hpp b/server/container-dbus-definitions.hpp index fe72e4d..0e280d4 100644 --- a/server/container-dbus-definitions.hpp +++ b/server/container-dbus-definitions.hpp @@ -25,12 +25,12 @@ #ifndef SERVER_CONTAINER_DBUS_DEFINITIONS_HPP #define SERVER_CONTAINER_DBUS_DEFINITIONS_HPP -#include +#include "common-dbus-definitions.hpp" namespace security_containers { namespace api { - +namespace container { const std::string BUS_NAME = "org.tizen.containers.domain"; const std::string OBJECT_PATH = "/org/tizen/containers/domain"; @@ -38,7 +38,6 @@ const std::string INTERFACE = "org.tizen.containers.doma const std::string METHOD_NOTIFY_ACTIVE_CONTAINER = "NotifyActiveContainer"; const std::string METHOD_FILE_MOVE_REQUEST = "FileMoveRequest"; -const std::string METHOD_PROXY_CALL = "ProxyCall"; const std::string SIGNAL_NOTIFICATION = "Notification"; const std::string FILE_MOVE_DESTINATION_NOT_FOUND = "FILE_MOVE_DESTINATION_NOT_FOUND"; @@ -78,7 +77,7 @@ const std::string DEFINITION = " " ""; - +} // namespace container } // namespace api } // namespace security_containers diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index b2c4222..012a8f7 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -24,6 +24,8 @@ #include "config.hpp" +#include "host-dbus-definitions.hpp" +#include "common-dbus-definitions.hpp" #include "container-dbus-definitions.hpp" #include "containers-manager.hpp" #include "container-admin.hpp" @@ -58,9 +60,6 @@ bool regexMatchVector(const std::string& str, const std::vector& v } const std::string HOST_ID = "host"; -const std::string DBUS_ERROR_NAME_FORBIDDEN = "org.tizen.containers.Error.Forbidden"; -const std::string DBUS_ERROR_NAME_FORWARDED = "org.tizen.containers.Error.Forwarded"; -const std::string DBUS_ERROR_NAME_UNKNOWN_TARGET = "org.tizen.containers.Error.UnknownTarget"; } // namespace @@ -84,6 +83,9 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet mHostConnection.setGetActiveContainerIdCallback(bind(&ContainersManager::handleGetActiveContainerIdCall, this, _1)); + mHostConnection.setSetActiveContainerCallback(bind(&ContainersManager::handleSetActiveContainerCall, + this, _1, _2)); + for (auto& containerConfig : mConfig.containerConfigs) { std::string containerConfigPath; @@ -138,7 +140,6 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet } } - ContainersManager::~ContainersManager() { LOGD("Destroying ContainersManager object..."); @@ -154,7 +155,6 @@ ContainersManager::~ContainersManager() LOGD("ContainersManager object destroyed"); } - void ContainersManager::focus(const std::string& containerId) { /* try to access the object first to throw immediately if it doesn't exist */ @@ -169,7 +169,6 @@ void ContainersManager::focus(const std::string& containerId) foregroundContainer->goForeground(); } - void ContainersManager::startAll() { LOGI("Starting all containers"); @@ -198,7 +197,6 @@ void ContainersManager::startAll() } } - void ContainersManager::stopAll() { LOGI("Stopping all containers"); @@ -208,7 +206,6 @@ void ContainersManager::stopAll() } } - std::string ContainersManager::getRunningForegroundContainerId() { for (auto& container : mContainers) { @@ -304,26 +301,26 @@ void ContainersManager::handleContainerMoveFileRequest(const std::string& srcCon ContainerMap::const_iterator dstIter = mContainers.find(dstContainerId); if (dstIter == mContainers.end()) { LOGE("Destination container '" << dstContainerId << "' not found"); - result->set(g_variant_new("(s)", api::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_DESTINATION_NOT_FOUND.c_str())); return; } Container& dstContanier = *dstIter->second; if (srcContainerId == dstContainerId) { LOGE("Cannot send a file to yourself"); - result->set(g_variant_new("(s)", api::FILE_MOVE_WRONG_DESTINATION.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_WRONG_DESTINATION.c_str())); return; } if (!regexMatchVector(path, srcContainer.getPermittedToSend())) { LOGE("Source container has no permissions to send the file: " << path); - result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_NO_PERMISSIONS_SEND.c_str())); return; } if (!regexMatchVector(path, dstContanier.getPermittedToRecv())) { LOGE("Destination container has no permissions to receive the file: " << path); - result->set(g_variant_new("(s)", api::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_NO_PERMISSIONS_RECEIVE.c_str())); return; } @@ -333,11 +330,11 @@ void ContainersManager::handleContainerMoveFileRequest(const std::string& srcCon if (!utils::moveFile(srcPath, dstPath)) { LOGE("Failed to move the file: " << path); - result->set(g_variant_new("(s)", api::FILE_MOVE_FAILED.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_FAILED.c_str())); } else { - result->set(g_variant_new("(s)", api::FILE_MOVE_SUCCEEDED.c_str())); + result->set(g_variant_new("(s)", api::container::FILE_MOVE_SUCCEEDED.c_str())); try { - dstContanier.sendNotification(srcContainerId, path, api::FILE_MOVE_SUCCEEDED); + dstContanier.sendNotification(srcContainerId, path, api::container::FILE_MOVE_SUCCEEDED); } catch (ServerException&) { LOGE("Notification to '" << dstContainerId << "' has not been sent"); } @@ -361,7 +358,7 @@ void ContainersManager::handleProxyCall(const std::string& caller, targetMethod)) { LOGW("Forbidden proxy call; " << caller << " -> " << target << "; " << targetBusName << "; " << targetObjectPath << "; " << targetInterface << "; " << targetMethod); - result->setError(DBUS_ERROR_NAME_FORBIDDEN, "Proxy call forbidden"); + result->setError(api::ERROR_FORBIDDEN, "Proxy call forbidden"); return; } @@ -373,7 +370,7 @@ void ContainersManager::handleProxyCall(const std::string& caller, GVariant* targetResult = asyncMethodCallResult.get(); result->set(g_variant_new("(v)", targetResult)); } catch (dbus::DbusException& e) { - result->setError(DBUS_ERROR_NAME_FORWARDED, e.what()); + result->setError(api::ERROR_FORWARDED, e.what()); } }; @@ -390,7 +387,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(DBUS_ERROR_NAME_UNKNOWN_TARGET, "Unknown proxy call target"); + result->setError(api::ERROR_UNKNOWN_ID, "Unknown proxy call target"); return; } @@ -445,4 +442,26 @@ void ContainersManager::handleGetActiveContainerIdCall(dbus::MethodResultBuilder } } +void ContainersManager::handleSetActiveContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result) +{ + LOGI("SetActiveContainer call; Id=" << 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"); + return; + } + + if (container->second->isStopped()){ + LOGE("Could not activate a stopped container"); + result->setError(api::host::ERROR_CONTAINER_STOPPED, + "Could not activate a stopped container"); + return; + } + + focus(id); + result->setVoid(); +} + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index b685028..33767a9 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -102,11 +102,12 @@ private: const std::string& targetMethod, GVariant* parameters, dbus::MethodResultBuilder::Pointer result); - void handleGetContainerDbuses(dbus::MethodResultBuilder::Pointer result); void handleDbusStateChanged(const std::string& containerId, const std::string& dbusAddress); void handleGetContainerIdsCall(dbus::MethodResultBuilder::Pointer result); void handleGetActiveContainerIdCall(dbus::MethodResultBuilder::Pointer result); + void handleSetActiveContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result); }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 0d96039..83ba8f8 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -51,19 +51,19 @@ HostConnection::HostConnection() mDbusConnection = dbus::DbusConnection::createSystem(); LOGT("Setting DBUS name"); - mDbusConnection->setName(hostapi::BUS_NAME, + mDbusConnection->setName(api::host::BUS_NAME, std::bind(&HostConnection::onNameAcquired, this), std::bind(&HostConnection::onNameLost, this)); if (!waitForName(NAME_ACQUIRED_TIMEOUT)) { - LOGE("Could not acquire dbus name: " << hostapi::BUS_NAME); - throw HostConnectionException("Could not acquire dbus name: " + hostapi::BUS_NAME); + LOGE("Could not acquire dbus name: " << api::host::BUS_NAME); + throw HostConnectionException("Could not acquire dbus name: " + api::host::BUS_NAME); } LOGT("Registering DBUS interface"); using namespace std::placeholders; - mDbusConnection->registerObject(hostapi::OBJECT_PATH, - hostapi::DEFINITION, + mDbusConnection->registerObject(api::host::OBJECT_PATH, + api::host::DEFINITION, std::bind(&HostConnection::onMessageCall, this, _1, _2, _3, _4, _5)); @@ -125,24 +125,39 @@ void HostConnection::setGetActiveContainerIdCallback(const GetActiveContainerIdC mGetActiveContainerIdCallback = callback; } +void HostConnection::setSetActiveContainerCallback(const SetActiveContainerCallback& callback) +{ + mSetActiveContainerCallback = callback; +} + void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, GVariant* parameters, dbus::MethodResultBuilder::Pointer result) { - if (objectPath != hostapi::OBJECT_PATH || interface != hostapi::INTERFACE) { + if (objectPath != api::host::OBJECT_PATH || interface != api::host::INTERFACE) { + return; + } + + if (methodName == api::host::METHOD_SET_ACTIVE_CONTAINER) { + const gchar* id = NULL; + g_variant_get(parameters, "(&s)", &id); + + if (mSetActiveContainerCallback) { + mSetActiveContainerCallback(id, result); + } return; } - if (methodName == hostapi::METHOD_GET_CONTAINER_DBUSES) { + if (methodName == api::host::METHOD_GET_CONTAINER_DBUSES) { if (mGetContainerDbusesCallback) { mGetContainerDbusesCallback(result); } return; } - if (methodName == hostapi::METHOD_PROXY_CALL) { + if (methodName == api::METHOD_PROXY_CALL) { const gchar* target = NULL; const gchar* targetBusName = NULL; const gchar* targetObjectPath = NULL; @@ -171,14 +186,14 @@ void HostConnection::onMessageCall(const std::string& objectPath, return; } - if (methodName == hostapi::METHOD_GET_CONTAINER_ID_LIST){ + if (methodName == api::host::METHOD_GET_CONTAINER_ID_LIST){ if (mGetContainerIdsCallback){ mGetContainerIdsCallback(result); } return; } - if (methodName == hostapi::METHOD_GET_ACTIVE_CONTAINER_ID){ + if (methodName == api::host::METHOD_GET_ACTIVE_CONTAINER_ID){ if (mGetActiveContainerIdCallback){ mGetActiveContainerIdCallback(result); } @@ -206,9 +221,9 @@ void HostConnection::signalContainerDbusState(const std::string& containerId, const std::string& dbusAddress) { GVariant* parameters = g_variant_new("(ss)", containerId.c_str(), dbusAddress.c_str()); - mDbusConnection->emitSignal(hostapi::OBJECT_PATH, - hostapi::INTERFACE, - hostapi::SIGNAL_CONTAINER_DBUS_STATE, + mDbusConnection->emitSignal(api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::SIGNAL_CONTAINER_DBUS_STATE, parameters); } diff --git a/server/host-connection.hpp b/server/host-connection.hpp index 962fbb9..bc9015d 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -51,13 +51,15 @@ public: GVariant* parameters, dbus::MethodResultBuilder::Pointer result )> ProxyCallCallback; - typedef std::function GetContainerDbusesCallback; - typedef std::function GetContainerIdsCallback; + typedef std::function GetContainerIdsCallback; typedef std::function GetActiveContainerIdCallback; - + typedef std::function SetActiveContainerCallback; /** * Register proxy call callback @@ -85,6 +87,11 @@ public: void setGetActiveContainerIdCallback(const GetContainerIdsCallback& callback); /** + * Register a callback called to set the active container + */ + void setSetActiveContainerCallback(const SetActiveContainerCallback& callback); + + /** * Make a proxy call */ void proxyCallAsync(const std::string& busName, @@ -104,6 +111,7 @@ private: GetContainerDbusesCallback mGetContainerDbusesCallback; GetContainerIdsCallback mGetContainerIdsCallback; GetActiveContainerIdCallback mGetActiveContainerIdCallback; + SetActiveContainerCallback mSetActiveContainerCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index ef30e1a..12e8d4a 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -25,23 +25,26 @@ #ifndef SERVER_HOST_DBUS_DEFINITIONS_HPP #define SERVER_HOST_DBUS_DEFINITIONS_HPP -#include +#include "common-dbus-definitions.hpp" namespace security_containers { -namespace hostapi { +namespace api { +namespace host { +const std::string BUS_NAME = "org.tizen.containers.host"; +const std::string OBJECT_PATH = "/org/tizen/containers/host"; +const std::string INTERFACE = "org.tizen.containers.host.manager"; -const std::string BUS_NAME = "org.tizen.containers.host"; -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 METHOD_PROXY_CALL = "ProxyCall"; -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_DBUSES = "GetContainerDbuses"; +const std::string METHOD_GET_CONTAINER_ID_LIST = "GetContainerIds"; +const std::string METHOD_GET_ACTIVE_CONTAINER_ID = "GetActiveContainerId"; +const std::string METHOD_SET_ACTIVE_CONTAINER = "SetActiveContainer"; + +const std::string SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState"; -const std::string SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState"; const std::string DEFINITION = "" @@ -64,6 +67,9 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " " " " " " " @@ -71,8 +77,8 @@ const std::string DEFINITION = " " ""; - -} // namespace hostapi +} // namespace host +} // namespace api } // namespace security_containers diff --git a/tests/unit_tests/server/ut-container-connection.cpp b/tests/unit_tests/server/ut-container-connection.cpp index 9f7b680..29dd310 100644 --- a/tests/unit_tests/server/ut-container-connection.cpp +++ b/tests/unit_tests/server/ut-container-connection.cpp @@ -28,6 +28,7 @@ #include "container-connection.hpp" #include "container-connection-transport.hpp" +#include "host-dbus-definitions.hpp" #include "container-dbus-definitions.hpp" // TODO: Switch to real power-manager dbus defs when they will be implemented in power-manager #include "fake-power-manager-dbus-definitions.hpp" @@ -152,10 +153,10 @@ BOOST_AUTO_TEST_CASE(NotifyActiveContainerApiTest) connection->setNotifyActiveContainerCallback(callback); DbusConnection::Pointer client = DbusConnection::create(dbus.acquireAddress()); - client->callMethod(api::BUS_NAME, - api::OBJECT_PATH, - api::INTERFACE, - api::METHOD_NOTIFY_ACTIVE_CONTAINER, + client->callMethod(api::container::BUS_NAME, + api::container::OBJECT_PATH, + api::container::INTERFACE, + api::container::METHOD_NOTIFY_ACTIVE_CONTAINER, g_variant_new("(ss)", "testapp", "testmessage"), "()"); BOOST_CHECK(notifyCalled.wait(EVENT_TIMEOUT)); @@ -178,9 +179,9 @@ BOOST_AUTO_TEST_CASE(SignalNotificationApiTest) const std::string& interface, const std::string& signalName, GVariant* parameters) { - if (objectPath == api::OBJECT_PATH && - interface == api::INTERFACE && - signalName == api::SIGNAL_NOTIFICATION && + if (objectPath == api::container::OBJECT_PATH && + interface == api::container::INTERFACE && + signalName == api::container::SIGNAL_NOTIFICATION && g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { const gchar* container = NULL; @@ -194,7 +195,7 @@ BOOST_AUTO_TEST_CASE(SignalNotificationApiTest) } } }; - client->signalSubscribe(handler, api::BUS_NAME); + client->signalSubscribe(handler, api::container::BUS_NAME); connection->sendNotification("testcontainer", "testapp", "testmessage"); diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index d4708e3..b3ce809 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -72,6 +72,7 @@ const std::string TEST_MESSAGE = "testmessage"; const std::string FILE_CONTENT = "File content\n" "Line 1\n" "Line 2\n"; +const std::string NON_EXISTANT_CONTAINER_ID = "NON_EXISTANT_CONTAINER_ID"; class DbusAccessory { public: @@ -126,7 +127,7 @@ public: void signalSubscribe(const DbusConnection::SignalCallback& callback) { - mClient->signalSubscribe(callback, isHost() ? hostapi::BUS_NAME : api::BUS_NAME); + mClient->signalSubscribe(callback, isHost() ? api::host::BUS_NAME : api::container::BUS_NAME); } void emitSignal(const std::string& objectPath, @@ -140,10 +141,10 @@ public: void callMethodNotify() { GVariant* parameters = g_variant_new("(ss)", TEST_APP_NAME.c_str(), TEST_MESSAGE.c_str()); - mClient->callMethod(api::BUS_NAME, - api::OBJECT_PATH, - api::INTERFACE, - api::METHOD_NOTIFY_ACTIVE_CONTAINER, + mClient->callMethod(api::container::BUS_NAME, + api::container::OBJECT_PATH, + api::container::INTERFACE, + api::container::METHOD_NOTIFY_ACTIVE_CONTAINER, parameters, "()"); } @@ -151,10 +152,10 @@ public: std::string callMethodMove(const std::string& dest, const std::string& path) { GVariant* parameters = g_variant_new("(ss)", dest.c_str(), path.c_str()); - GVariantPtr result = mClient->callMethod(api::BUS_NAME, - api::OBJECT_PATH, - api::INTERFACE, - api::METHOD_FILE_MOVE_REQUEST, + GVariantPtr result = mClient->callMethod(api::container::BUS_NAME, + api::container::OBJECT_PATH, + api::container::INTERFACE, + api::container::METHOD_FILE_MOVE_REQUEST, parameters, "(s)"); @@ -212,10 +213,13 @@ public: interface.c_str(), method.c_str(), parameters); - GVariantPtr result = mClient->callMethod(isHost() ? hostapi::BUS_NAME : api::BUS_NAME, - isHost() ? hostapi::OBJECT_PATH : api::OBJECT_PATH, - isHost() ? hostapi::INTERFACE : api::INTERFACE, - isHost() ? hostapi::METHOD_PROXY_CALL : api::METHOD_PROXY_CALL, + GVariantPtr result = mClient->callMethod(isHost() ? api::host::BUS_NAME : + api::container::BUS_NAME, + isHost() ? api::host::OBJECT_PATH : + api::container::OBJECT_PATH, + isHost() ? api::host::INTERFACE : + api::container::INTERFACE, + api::METHOD_PROXY_CALL, packedParameters, "(v)"); GVariant* unpackedResult = NULL; @@ -227,10 +231,10 @@ public: { assert(isHost()); Dbuses dbuses; - GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, - hostapi::OBJECT_PATH, - hostapi::INTERFACE, - hostapi::METHOD_GET_CONTAINER_DBUSES, + GVariantPtr result = mClient->callMethod(api::host::BUS_NAME, + api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::METHOD_GET_CONTAINER_DBUSES, NULL, "(a{ss})"); GVariant* array = NULL; @@ -249,10 +253,10 @@ public: std::vector callMethodGetContainerIds() { assert(isHost()); - GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, - hostapi::OBJECT_PATH, - hostapi::INTERFACE, - hostapi::METHOD_GET_CONTAINER_ID_LIST, + GVariantPtr result = mClient->callMethod(api::host::BUS_NAME, + api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::METHOD_GET_CONTAINER_ID_LIST, NULL, "(as)"); @@ -274,10 +278,10 @@ public: std::string callMethodGetActiveContainerId() { assert(isHost()); - GVariantPtr result = mClient->callMethod(hostapi::BUS_NAME, - hostapi::OBJECT_PATH, - hostapi::INTERFACE, - hostapi::METHOD_GET_ACTIVE_CONTAINER_ID, + GVariantPtr result = mClient->callMethod(api::host::BUS_NAME, + api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::METHOD_GET_ACTIVE_CONTAINER_ID, NULL, "(s)"); @@ -286,6 +290,19 @@ public: return containerId; } + void callMethodSetActiveContainer(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_SET_ACTIVE_CONTAINER, + parameters, + "()"); + + } + private: const int mId; DbusConnection::Pointer mClient; @@ -413,9 +430,9 @@ BOOST_AUTO_TEST_CASE(NotifyActiveContainerTest) const std::string& signalName, GVariant* parameters) { - if (objectPath == api::OBJECT_PATH && - interface == api::INTERFACE && - signalName == api::SIGNAL_NOTIFICATION && + if (objectPath == api::container::OBJECT_PATH && + interface == api::container::INTERFACE && + signalName == api::container::SIGNAL_NOTIFICATION && g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { const gchar* container = NULL; @@ -516,9 +533,9 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) const std::string& signalName, GVariant* parameters) { - if (objectPath == api::OBJECT_PATH && - interface == api::INTERFACE && - signalName == api::SIGNAL_NOTIFICATION && + if (objectPath == api::container::OBJECT_PATH && + interface == api::container::INTERFACE && + signalName == api::container::SIGNAL_NOTIFICATION && g_variant_is_of_type(parameters, G_VARIANT_TYPE("(sss)"))) { const gchar* source = NULL; @@ -547,27 +564,27 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) // sending to a non existing container BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(BUGGY_CONTAINER, NO_PATH), - api::FILE_MOVE_DESTINATION_NOT_FOUND); + api::container::FILE_MOVE_DESTINATION_NOT_FOUND); BOOST_CHECK(notificationLatch.empty()); // sending to self BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER1, NO_PATH), - api::FILE_MOVE_WRONG_DESTINATION); + api::container::FILE_MOVE_WRONG_DESTINATION); BOOST_CHECK(notificationLatch.empty()); // no permission to send BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, "/etc/secret1"), - api::FILE_MOVE_NO_PERMISSIONS_SEND); + api::container::FILE_MOVE_NO_PERMISSIONS_SEND); BOOST_CHECK(notificationLatch.empty()); // no permission to receive BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, "/etc/secret2"), - api::FILE_MOVE_NO_PERMISSIONS_RECEIVE); + api::container::FILE_MOVE_NO_PERMISSIONS_RECEIVE); BOOST_CHECK(notificationLatch.empty()); // non existing file BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, BUGGY_PATH), - api::FILE_MOVE_FAILED); + api::container::FILE_MOVE_FAILED); BOOST_CHECK(notificationLatch.empty()); // a working scenario @@ -580,12 +597,12 @@ BOOST_AUTO_TEST_CASE(MoveFileTest) BOOST_REQUIRE(utils::saveFileContent(CONTAINER1PATH + "/file", FILE_CONTENT)); BOOST_CHECK_EQUAL(dbuses.at(1)->callMethodMove(CONTAINER2, TMP + "/file"), - api::FILE_MOVE_SUCCEEDED); + api::container::FILE_MOVE_SUCCEEDED); BOOST_CHECK(notificationLatch.wait(EVENT_TIMEOUT)); BOOST_CHECK(notificationLatch.empty()); BOOST_CHECK_EQUAL(notificationSource, CONTAINER1); BOOST_CHECK_EQUAL(notificationPath, TMP + "/file"); - BOOST_CHECK_EQUAL(notificationRetcode, api::FILE_MOVE_SUCCEEDED); + BOOST_CHECK_EQUAL(notificationRetcode, api::container::FILE_MOVE_SUCCEEDED); BOOST_CHECK(!fs::exists(CONTAINER1PATH + "/file")); BOOST_CHECK_EQUAL(utils::readFileContent(CONTAINER2PATH + "/file"), FILE_CONTENT); @@ -756,9 +773,9 @@ BOOST_AUTO_TEST_CASE(ContainerDbusesSignalsTest) const std::string& interface, const std::string& signalName, GVariant* parameters) { - if (objectPath == hostapi::OBJECT_PATH && - interface == hostapi::INTERFACE && - signalName == hostapi::SIGNAL_CONTAINER_DBUS_STATE) { + if (objectPath == api::host::OBJECT_PATH && + interface == api::host::INTERFACE && + signalName == api::host::SIGNAL_CONTAINER_DBUS_STATE) { const gchar* containerId = NULL; const gchar* dbusAddress = NULL; @@ -827,4 +844,28 @@ BOOST_AUTO_TEST_CASE(GetActiveContainerIdTest) BOOST_CHECK(dbus.callMethodGetActiveContainerId() == ""); } +BOOST_AUTO_TEST_CASE(SetActiveContainerTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + cm.startAll(); + + DbusAccessory dbus(DbusAccessory::HOST_ID); + + std::vector containerIds = {"ut-containers-manager-console1-dbus", + "ut-containers-manager-console2-dbus", + "ut-containers-manager-console3-dbus"}; + + for (std::string& containerId: containerIds){ + BOOST_REQUIRE_NO_THROW(dbus.callMethodSetActiveContainer(containerId)); + BOOST_CHECK(dbus.callMethodGetActiveContainerId() == containerId); + } + + BOOST_REQUIRE_THROW(dbus.callMethodSetActiveContainer(NON_EXISTANT_CONTAINER_ID), + DbusException); + + cm.stopAll(); + BOOST_REQUIRE_THROW(dbus.callMethodSetActiveContainer("ut-containers-manager-console1-dbus"), + DbusException); +} + BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From d4af3ccd9e4b36bcce46bbadb07f65519f3369e5 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Tue, 29 Jul 2014 12:33:10 +0200 Subject: [PATCH 14/16] Fix client library installation [Bug/Feature] Missing so versioning [Cause] N/A [Solution] N/A [Verification] Build, install Change-Id: I4f5c3715b177506c6c6e967512acf969944fa246 --- client/CMakeLists.txt | 17 ++++++++++------- client/security-containers.pc.in | 6 ++++-- packaging/security-containers.spec | 11 +++++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 8d45be5..8a34575 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -21,10 +21,14 @@ MESSAGE(STATUS "Generating makefile for the Client...") FILE(GLOB project_SRCS *.cpp *.hpp) FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp) +SET(_LIB_VERSION_ "0.0.1") +SET(_LIB_SOVERSION_ "0") +SET(PC_FILE "${PROJECT_NAME}.pc") ## Setup target ################################################################ -SET(CLIENT_CODENAME "${PROJECT_NAME}-client") -ADD_LIBRARY(${CLIENT_CODENAME} SHARED ${project_SRCS}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${project_SRCS}) +SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY SOVERSION ${_LIB_SOVERSION_}) +SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY VERSION ${_LIB_VERSION_}) ## Link libraries ############################################################## @@ -32,17 +36,16 @@ INCLUDE_DIRECTORIES(${COMMON_FOLDER}) ## Generate the pc file ######################################################## -CONFIGURE_FILE(security-containers.pc.in - ${CMAKE_BINARY_DIR}/security-containers.pc @ONLY) +CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_BINARY_DIR}/${PC_FILE} @ONLY) ## Install ##################################################################### -INSTALL(FILES ${CMAKE_BINARY_DIR}/security-containers.pc +INSTALL(FILES ${CMAKE_BINARY_DIR}/${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -INSTALL(TARGETS ${CLIENT_CODENAME} +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT RuntimeLibraries) INSTALL(FILES security-containers-client.h - DESTINATION ${INCLUDE_INSTALL_DIR}/security-containers) + DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}) diff --git a/client/security-containers.pc.in b/client/security-containers.pc.in index 16a4330..186218e 100644 --- a/client/security-containers.pc.in +++ b/client/security-containers.pc.in @@ -1,10 +1,12 @@ +# Package Information for pkg-config + prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=@LIB_INSTALL_DIR@ includedir=${prefix}/include Name: security-containers -Description: Security Containers Package -Version: @PACKAGE_VERSION@ +Description: Security Containers library +Version: @_LIB_VERSION_@ Libs: -L${libdir} -lsecurity-containers-client Cflags: -I${includedir}/security-containers diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index e639a98..af4751c 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -113,7 +113,13 @@ Library interface to the security-containers daemon %files client %manifest packaging/libsecurity-containers-client.manifest -%attr(644,root,root) %{_libdir}/libsecurity-containers-client.so +%defattr(644,root,root,755) +%attr(755,root,root) %{_libdir}/libsecurity-containers.so.0.0.1 +%{_libdir}/libsecurity-containers.so.0 + +%post client -p /sbin/ldconfig + +%postun client -p /sbin/ldconfig ## Devel Package ############################################################### @@ -129,8 +135,9 @@ Development package including the header files for the client library %files devel %manifest packaging/security-containers.manifest %defattr(644,root,root,755) +%{_libdir}/libsecurity-containers.so %{_includedir}/security-containers -%{_libdir}/pkgconfig/* +%{_libdir}/pkgconfig/*.pc ## Container Support Package ################################################### -- 2.7.4 From 907f1db9a197eab354dce2fff1007e6b235ff985 Mon Sep 17 00:00:00 2001 From: Jacek Pielaszkiewicz Date: Mon, 21 Jul 2014 17:09:35 +0200 Subject: [PATCH 15/16] Extract common/log, common/dbus, common/config directories and create from them libraries. [Bug/Feature] N/A [Cause] N/A [Solution] 1. The following directories have been extracted (removed): - common/log - common/dbus - common/config 2. In place of the removed source code, security-containers is link with the following libraries: - libLogger - libSimpleDbus - libConfig [Verification] Build, install, run tests Change-Id: I9d0b1627638b401bb88e442dd9681a7943fe0b5d Signed-off-by: Jacek Pielaszkiewicz --- common/config/exception.hpp | 51 --- common/config/fields.hpp | 77 ---- common/config/from-json-visitor.hpp | 143 -------- common/config/is-visitable.hpp | 55 --- common/config/manager.hpp | 77 ---- common/config/to-json-visitor.hpp | 124 ------- common/dbus/connection.cpp | 391 --------------------- common/dbus/connection.hpp | 204 ----------- common/dbus/exception.hpp | 81 ----- common/libvirt/connection.cpp | 2 +- common/libvirt/domain.cpp | 2 +- common/libvirt/helpers.cpp | 2 +- common/libvirt/network.cpp | 2 +- common/log/backend-journal.cpp | 72 ---- common/log/backend-journal.hpp | 52 --- common/log/backend-null.hpp | 53 --- common/log/backend-stderr.cpp | 65 ---- common/log/backend-stderr.hpp | 52 --- common/log/backend.hpp | 55 --- common/log/ccolor.cpp | 44 --- common/log/ccolor.hpp | 56 --- common/log/formatter.cpp | 124 ------- common/log/formatter.hpp | 52 --- common/log/level.cpp | 70 ---- common/log/level.hpp | 58 --- common/log/logger.cpp | 86 ----- common/log/logger.hpp | 87 ----- common/utils/callback-guard.cpp | 2 +- common/utils/environment.cpp | 2 +- common/utils/fs.cpp | 2 +- container-daemon/CMakeLists.txt | 3 +- container-daemon/daemon-connection.cpp | 2 +- container-daemon/daemon.cpp | 2 +- container-daemon/main.cpp | 8 +- container-daemon/runner.cpp | 2 +- packaging/security-containers.spec | 3 + server/CMakeLists.txt | 2 +- server/container-admin.cpp | 2 +- server/container-connection-transport.cpp | 2 +- server/container-connection.cpp | 2 +- server/container.cpp | 3 +- server/containers-manager.cpp | 3 +- server/host-connection.cpp | 2 +- server/input-monitor.cpp | 2 +- server/main.cpp | 8 +- server/network-admin.cpp | 2 +- server/server.cpp | 3 +- tests/unit_tests/CMakeLists.txt | 2 +- tests/unit_tests/config/ut-configuration.cpp | 3 +- tests/unit_tests/dbus/test-server.cpp | 2 +- tests/unit_tests/dbus/ut-connection.cpp | 4 +- tests/unit_tests/log/ut-logger.cpp | 10 +- .../unit_tests/server/ut-container-connection.cpp | 2 +- tests/unit_tests/server/ut-container.cpp | 2 +- tests/unit_tests/server/ut-containers-manager.cpp | 6 +- tests/unit_tests/server/ut-server.cpp | 2 +- tests/unit_tests/ut.cpp | 6 +- tests/unit_tests/utils/scoped-daemon.cpp | 2 +- 58 files changed, 56 insertions(+), 2179 deletions(-) delete mode 100644 common/config/exception.hpp delete mode 100644 common/config/fields.hpp delete mode 100644 common/config/from-json-visitor.hpp delete mode 100644 common/config/is-visitable.hpp delete mode 100644 common/config/manager.hpp delete mode 100644 common/config/to-json-visitor.hpp delete mode 100644 common/dbus/connection.cpp delete mode 100644 common/dbus/connection.hpp delete mode 100644 common/dbus/exception.hpp delete mode 100644 common/log/backend-journal.cpp delete mode 100644 common/log/backend-journal.hpp delete mode 100644 common/log/backend-null.hpp delete mode 100644 common/log/backend-stderr.cpp delete mode 100644 common/log/backend-stderr.hpp delete mode 100644 common/log/backend.hpp delete mode 100644 common/log/ccolor.cpp delete mode 100644 common/log/ccolor.hpp delete mode 100644 common/log/formatter.cpp delete mode 100644 common/log/formatter.hpp delete mode 100644 common/log/level.cpp delete mode 100644 common/log/level.hpp delete mode 100644 common/log/logger.cpp delete mode 100644 common/log/logger.hpp diff --git a/common/config/exception.hpp b/common/config/exception.hpp deleted file mode 100644 index aa644b1..0000000 --- a/common/config/exception.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Lukasz Pawelczyk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com) - * @brief Exceptions for the configuration - */ - - -#ifndef COMMON_CONFIG_EXCEPTION_HPP -#define COMMON_CONFIG_EXCEPTION_HPP - -#include "base-exception.hpp" - - -namespace security_containers { -namespace config { - - -/** - * Base class for exceptions in configuration. - * Error occured during a config file parsing, - * e.g. syntax error - */ -struct ConfigException: public SecurityContainersException { - - ConfigException(const std::string& error = "") : SecurityContainersException(error) {} -}; - - -} // namespace config -} // namespace security_containers - - -#endif // COMMON_CONFIG_EXCEPTION_HPP diff --git a/common/config/fields.hpp b/common/config/fields.hpp deleted file mode 100644 index db0f26f..0000000 --- a/common/config/fields.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Macros for registering configuration fields - */ - -#ifndef COMMON_CONFIG_FIELDS_HPP -#define COMMON_CONFIG_FIELDS_HPP - -#include -#include - -#if BOOST_PP_VARIADICS != 1 -#error variadic macros not supported -#endif - -/** - * Use this macro to register config fields. - * - * Example: - * struct Foo - * { - * std::string bar; - * std::vector tab; - * - * // SubConfigA must also register config fields - * SubConfigA sub_a; - * - * // SubConfigB must also register config fields - * std::vector tab_sub; - * - * CONFIG_REGISTER - * ( - * bar, - * tab, - * sub_a - * ) - * }; - */ -#define CONFIG_REGISTER(...) \ - template \ - void accept(Visitor v) { \ - GENERATE_ELEMENTS__(__VA_ARGS__) \ - } \ - template \ - void accept(Visitor v) const { \ - GENERATE_ELEMENTS__(__VA_ARGS__) \ - } \ - -#define GENERATE_ELEMENTS__(...) \ - BOOST_PP_LIST_FOR_EACH(GENERATE_ELEMENT__, \ - _, \ - BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__)) \ - -#define GENERATE_ELEMENT__(r, _, element) \ - v.visit(#element, element); \ - - -#endif // COMMON_CONFIG_FIELDS_HPP diff --git a/common/config/from-json-visitor.hpp b/common/config/from-json-visitor.hpp deleted file mode 100644 index fad9986..0000000 --- a/common/config/from-json-visitor.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief JSON visitor - */ - -#ifndef COMMON_CONFIG_FROM_JSON_VISITOR_HPP -#define COMMON_CONFIG_FROM_JSON_VISITOR_HPP - -#include "config/is-visitable.hpp" -#include "config/exception.hpp" - -#include -#include -#include - -namespace security_containers { -namespace config { - -class FromJsonVisitor { -public: - explicit FromJsonVisitor(const std::string& jsonString) - : mObject(nullptr) - { - mObject = json_tokener_parse(jsonString.c_str()); - if (mObject == nullptr) { - throw ConfigException("Json parsing error"); - } - } - - FromJsonVisitor(const FromJsonVisitor& visitor) - : mObject(json_object_get(visitor.mObject)) - { - } - - ~FromJsonVisitor() - { - json_object_put(mObject); - } - - template - void visit(const std::string& name, T& value) - { - json_object* object = nullptr; - if (!json_object_object_get_ex(mObject, name.c_str(), &object)) { - throw ConfigException("Missing field '" + name + "' in json"); - } - fromJsonObject(object, value); - } - -private: - json_object* mObject; - - FromJsonVisitor& operator=(const FromJsonVisitor&) = delete; - - explicit FromJsonVisitor(json_object* object) - : mObject(json_object_get(object)) - { - } - - static void checkType(json_object* object, json_type type) - { - if (type != json_object_get_type(object)) { - throw ConfigException("Invalid field type"); - } - } - - static void fromJsonObject(json_object* object, int& value) - { - checkType(object, json_type_int); - std::int64_t value64 = json_object_get_int64(object); - if (value64 > INT32_MAX || value64 < INT32_MIN) { - throw ConfigException("Value out of range"); - } - value = static_cast(value64); - } - - static void fromJsonObject(json_object* object, std::int64_t& value) - { - checkType(object, json_type_int); - value = json_object_get_int64(object); - } - - static void fromJsonObject(json_object* object, bool& value) - { - checkType(object, json_type_boolean); - value = json_object_get_boolean(object); - } - - static void fromJsonObject(json_object* object, double& value) - { - checkType(object, json_type_double); - value = json_object_get_double(object); - } - - static void fromJsonObject(json_object* object, std::string& value) - { - checkType(object, json_type_string); - value = json_object_get_string(object); - } - - template - static void fromJsonObject(json_object* object, std::vector& value) - { - checkType(object, json_type_array); - int length = json_object_array_length(object); - value.resize(static_cast(length)); - for (int i = 0; i < length; ++i) { - fromJsonObject(json_object_array_get_idx(object, i), value[static_cast(i)]); - } - } - - template::value>::type> - static void fromJsonObject(json_object* object, T& value) - { - checkType(object, json_type_object); - FromJsonVisitor visitor(object); - value.accept(visitor); - } -}; - -} // namespace config -} // namespace security_containers - -#endif // COMMON_CONFIG_FROM_JSON_VISITOR_HPP diff --git a/common/config/is-visitable.hpp b/common/config/is-visitable.hpp deleted file mode 100644 index 0a405c5..0000000 --- a/common/config/is-visitable.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Internal configuration helper - */ - -#ifndef COMMON_CONFIG_IS_VISITABLE_HPP -#define COMMON_CONFIG_IS_VISITABLE_HPP - -#include - -namespace security_containers { -namespace config { - -template -struct isVisitableHelper__ { - struct Visitor {}; - - template static std::true_type - test(decltype(std::declval().template accept(Visitor()))*); - - template static std::false_type - test(...); - - static constexpr bool value = std::is_same(0)), std::true_type>::value; -}; - -/** - * Helper for compile-time checking against existance of template method 'accept'. - */ -template -struct isVisitable : public std::integral_constant::value> {}; - -} // namespace config -} // namespace security_containers - -#endif // COMMON_CONFIG_IS_VISITABLE_HPP diff --git a/common/config/manager.hpp b/common/config/manager.hpp deleted file mode 100644 index 8761267..0000000 --- a/common/config/manager.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Configuration management functions - */ - -#ifndef COMMON_CONFIG_MANAGER_HPP -#define COMMON_CONFIG_MANAGER_HPP - -#include "config/to-json-visitor.hpp" -#include "config/from-json-visitor.hpp" -#include "config/is-visitable.hpp" -#include "utils/fs.hpp" - -namespace security_containers { -namespace config { - -template -void loadFromString(const std::string& jsonString, Config& config) -{ - static_assert(isVisitable::value, "Use CONFIG_REGISTER macro"); - - FromJsonVisitor visitor(jsonString); - config.accept(visitor); -} - -template -std::string saveToString(const Config& config) -{ - static_assert(isVisitable::value, "Use CONFIG_REGISTER macro"); - - ToJsonVisitor visitor; - config.accept(visitor); - return visitor.toString(); -} - -template -void loadFromFile(const std::string& filename, Config& config) -{ - std::string content; - if (!utils::readFileContent(filename, content)) { - throw ConfigException("Could not load " + filename); - } - loadFromString(content, config); -} - -template -void saveToFile(const std::string& filename, const Config& config) -{ - const std::string content = saveToString(config); - if (!utils::saveFileContent(filename, content)) { - throw ConfigException("Could not save " + filename); - } -} - -} // namespace config -} // namespace security_containers - -#endif // COMMON_CONFIG_MANAGER_HPP diff --git a/common/config/to-json-visitor.hpp b/common/config/to-json-visitor.hpp deleted file mode 100644 index 477b1ef..0000000 --- a/common/config/to-json-visitor.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief JSON visitor - */ - -#ifndef COMMON_CONFIG_TO_JSON_VISITOR_HPP -#define COMMON_CONFIG_TO_JSON_VISITOR_HPP - -#include "config/is-visitable.hpp" - -#include -#include -#include - -namespace security_containers { -namespace config { - -class ToJsonVisitor { - -public: - ToJsonVisitor() - : mObject(json_object_new_object()) - { - } - - ToJsonVisitor(const ToJsonVisitor& visitor) - : mObject(json_object_get(visitor.mObject)) - { - } - - ~ToJsonVisitor() - { - json_object_put(mObject); - } - - std::string toString() const - { - return json_object_to_json_string(mObject); - } - - template - void visit(const std::string& name, const T& value) - { - json_object_object_add(mObject, name.c_str(), toJsonObject(value)); - } -private: - json_object* mObject; - - ToJsonVisitor& operator=(const ToJsonVisitor&) = delete; - - json_object* detach() - { - json_object* ret = mObject; - mObject = nullptr; - return ret; - } - - static json_object* toJsonObject(int value) - { - return json_object_new_int(value); - } - - static json_object* toJsonObject(std::int64_t value) - { - return json_object_new_int64(value); - } - - static json_object* toJsonObject(bool value) - { - return json_object_new_boolean(value); - } - - static json_object* toJsonObject(double value) - { - return json_object_new_double(value); - } - - static json_object* toJsonObject(const std::string& value) - { - return json_object_new_string(value.c_str()); - } - - template - static json_object* toJsonObject(const std::vector& value) - { - json_object* array = json_object_new_array(); - for (const T& v : value) { - json_object_array_add(array, toJsonObject(v)); - } - return array; - } - - template::value>::type> - static json_object* toJsonObject(const T& value) - { - ToJsonVisitor visitor; - value.accept(visitor); - return visitor.detach(); - } -}; - -} // namespace config -} // namespace security_containers - -#endif // COMMON_CONFIG_TO_JSON_VISITOR_HPP diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp deleted file mode 100644 index ef6fc46..0000000 --- a/common/dbus/connection.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Dbus connection class - */ - -#include "config.hpp" -#include "dbus/connection.hpp" -#include "dbus/exception.hpp" -#include "utils/callback-wrapper.hpp" -#include "utils/scoped-gerror.hpp" -#include "log/logger.hpp" - -using namespace security_containers::utils; - -namespace security_containers { -namespace dbus { - - -namespace { - -const std::string SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"; -const std::string INTROSPECT_INTERFACE = "org.freedesktop.DBus.Introspectable"; -const std::string INTROSPECT_METHOD = "Introspect"; - -const int CALL_METHOD_TIMEOUT_MS = 1000; - -class MethodResultBuilderImpl : public MethodResultBuilder { -public: - MethodResultBuilderImpl(GDBusMethodInvocation* invocation) - : mInvocation(invocation), mResultSet(false) {} - ~MethodResultBuilderImpl() - { - if (!mResultSet) { - setError("org.freedesktop.DBus.Error.UnknownMethod", "Not implemented"); - } - } - void set(GVariant* parameters) - { - g_dbus_method_invocation_return_value(mInvocation, parameters); - mResultSet = true; - } - void setVoid() - { - set(NULL); - } - void setError(const std::string& name, const std::string& message) - { - g_dbus_method_invocation_return_dbus_error(mInvocation, name.c_str(), message.c_str()); - mResultSet = true; - } -private: - GDBusMethodInvocation* mInvocation; - bool mResultSet; -}; - -void throwDbusException(const ScopedGError& e) -{ - if (e->domain == g_io_error_quark()) { - if (e->code == G_IO_ERROR_DBUS_ERROR) { - throw DbusCustomException(e->message); - } else { - throw DbusIOException(e->message); - } - } else if (e->domain == g_dbus_error_quark()) { - throw DbusOperationException(e->message); - } else if (e->domain == g_markup_error_quark()) { - throw DbusInvalidArgumentException(e->message); - } else { - throw DbusException(e->message); - } -} - -class AsyncMethodCallResultImpl : public AsyncMethodCallResult { -public: - AsyncMethodCallResultImpl(GVariant* result, const ScopedGError& error) - : mResult(result), mError(error) {} - ~AsyncMethodCallResultImpl() - { - if (mResult) { - g_variant_unref(mResult); - } - } - GVariant* get() - { - if (mError) { - throwDbusException(mError); - } - return mResult; - } -private: - GVariant* mResult; - const ScopedGError& mError; -}; - -} // namespace - -DbusConnection::Pointer DbusConnection::create(const std::string& address) -{ - return Pointer(new DbusConnection(address)); -} - -DbusConnection::Pointer DbusConnection::createSystem() -{ - return create(SYSTEM_BUS_ADDRESS); -} - -DbusConnection::DbusConnection(const std::string& address) - : mConnection(NULL) - , mNameId(0) -{ - ScopedGError error; - const GDBusConnectionFlags flags = - static_cast(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | - G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION); - // TODO: this is possible deadlock if the dbus - // socket exists but there is no dbus-daemon - mConnection = g_dbus_connection_new_for_address_sync(address.c_str(), - flags, - NULL, - NULL, - &error); - if (error) { - error.strip(); - LOGE("Could not connect to " << address << "; " << error); - throwDbusException(error); - } -} - -DbusConnection::~DbusConnection() -{ - if (mNameId) { - g_bus_unown_name(mNameId); - } - g_object_unref(mConnection); - LOGT("Connection deleted"); -} - -void DbusConnection::setName(const std::string& name, - const VoidCallback& onNameAcquired, - const VoidCallback& onNameLost) -{ - mNameId = g_bus_own_name_on_connection(mConnection, - name.c_str(), - G_BUS_NAME_OWNER_FLAGS_NONE, - &DbusConnection::onNameAcquired, - &DbusConnection::onNameLost, - utils::createCallbackWrapper( - NameCallbacks(onNameAcquired, onNameLost), - mGuard.spawn()), - &utils::deleteCallbackWrapper); -} - -void DbusConnection::onNameAcquired(GDBusConnection*, const gchar* name, gpointer userData) -{ - LOGD("Name acquired " << name); - const NameCallbacks& callbacks = utils::getCallbackFromPointer(userData); - if (callbacks.nameAcquired) { - callbacks.nameAcquired(); - } -} - -void DbusConnection::onNameLost(GDBusConnection*, const gchar* name, gpointer userData) -{ - LOGD("Name lost " << name); - const NameCallbacks& callbacks = utils::getCallbackFromPointer(userData); - if (callbacks.nameLost) { - callbacks.nameLost(); - } -} - -void DbusConnection::emitSignal(const std::string& objectPath, - const std::string& interface, - const std::string& name, - GVariant* parameters) -{ - ScopedGError error; - g_dbus_connection_emit_signal(mConnection, - NULL, - objectPath.c_str(), - interface.c_str(), - name.c_str(), - parameters, - &error); - if (error) { - error.strip(); - LOGE("Emit signal failed; " << error); - throwDbusException(error); - } -} - -void DbusConnection::signalSubscribe(const SignalCallback& callback, - const std::string& senderBusName) -{ - g_dbus_connection_signal_subscribe(mConnection, - senderBusName.empty() ? NULL : senderBusName.c_str(), - NULL, - NULL, - NULL, - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - &DbusConnection::onSignal, - utils::createCallbackWrapper(callback, mGuard.spawn()), - &utils::deleteCallbackWrapper); -} - -void DbusConnection::onSignal(GDBusConnection*, - const gchar* sender, - const gchar* object, - const gchar* interface, - const gchar* name, - GVariant* parameters, - gpointer userData) -{ - const SignalCallback& callback = utils::getCallbackFromPointer(userData); - - LOGD("Signal: " << sender << "; " << object << "; " << interface << "; " << name); - - if (callback) { - callback(sender, object, interface, name, parameters); - } -} - -std::string DbusConnection::introspect(const std::string& busName, const std::string& objectPath) -{ - GVariantPtr result = DbusConnection::callMethod(busName, - objectPath, - INTROSPECT_INTERFACE, - INTROSPECT_METHOD, - NULL, - "(s)"); - const gchar* xml; - g_variant_get(result.get(), "(&s)", &xml); - return xml; -} - -void DbusConnection::registerObject(const std::string& objectPath, - const std::string& objectDefinitionXml, - const MethodCallCallback& callback) -{ - ScopedGError error; - GDBusNodeInfo* nodeInfo = g_dbus_node_info_new_for_xml(objectDefinitionXml.c_str(), &error); - if (nodeInfo != NULL && (nodeInfo->interfaces == NULL || - nodeInfo->interfaces[0] == NULL || - nodeInfo->interfaces[1] != NULL)) { - g_dbus_node_info_unref(nodeInfo); - g_set_error(&error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_INVALID_CONTENT, - "Expected exactly one interface"); - } - if (error) { - error.strip(); - LOGE("Invalid xml; " << error); - throwDbusException(error); - } - GDBusInterfaceInfo* interfaceInfo = nodeInfo->interfaces[0]; - - GDBusInterfaceVTable vtable; - vtable.method_call = &DbusConnection::onMethodCall; - vtable.get_property = NULL; - vtable.set_property = NULL; - - g_dbus_connection_register_object(mConnection, - objectPath.c_str(), - interfaceInfo, - &vtable, - utils::createCallbackWrapper(callback, mGuard.spawn()), - &utils::deleteCallbackWrapper, - &error); - g_dbus_node_info_unref(nodeInfo); - if (error) { - error.strip(); - LOGE("Register object failed; " << error); - throwDbusException(error); - } -} - -void DbusConnection::onMethodCall(GDBusConnection*, - const gchar*, - const gchar* objectPath, - const gchar* interface, - const gchar* method, - GVariant* parameters, - GDBusMethodInvocation* invocation, - gpointer userData) -{ - const MethodCallCallback& callback = utils::getCallbackFromPointer(userData); - - LOGD("MethodCall: " << objectPath << "; " << interface << "; " << method); - - MethodResultBuilder::Pointer resultBuilder(new MethodResultBuilderImpl(invocation)); - if (callback) { - callback(objectPath, interface, method, parameters, resultBuilder); - } -} - -GVariantPtr DbusConnection::callMethod(const std::string& busName, - const std::string& objectPath, - const std::string& interface, - const std::string& method, - GVariant* parameters, - const std::string& replyType) -{ - ScopedGError error; - GVariant* result = g_dbus_connection_call_sync(mConnection, - busName.c_str(), - objectPath.c_str(), - interface.c_str(), - method.c_str(), - parameters, - replyType.empty() ? NULL - : G_VARIANT_TYPE(replyType.c_str()), - G_DBUS_CALL_FLAGS_NONE, - CALL_METHOD_TIMEOUT_MS, - NULL, - &error); - if (error) { - error.strip(); - LOGE("Call method failed; " << error); - throwDbusException(error); - } - return GVariantPtr(result, g_variant_unref); -} - -void DbusConnection::callMethodAsync(const std::string& busName, - const std::string& objectPath, - const std::string& interface, - const std::string& method, - GVariant* parameters, - const std::string& replyType, - const AsyncMethodCallCallback& callback) -{ - g_dbus_connection_call(mConnection, - busName.c_str(), - objectPath.c_str(), - interface.c_str(), - method.c_str(), - parameters, - replyType.empty() ? NULL - : G_VARIANT_TYPE(replyType.c_str()), - G_DBUS_CALL_FLAGS_NONE, - CALL_METHOD_TIMEOUT_MS, - NULL, - &DbusConnection::onAsyncReady, - utils::createCallbackWrapper(callback, mGuard.spawn())); -} - -void DbusConnection::onAsyncReady(GObject* source, - GAsyncResult* asyncResult, - gpointer userData) -{ - std::unique_ptr - autoDeleteCallback(userData, &utils::deleteCallbackWrapper); - GDBusConnection* connection = reinterpret_cast(source); - const AsyncMethodCallCallback& callback = - utils::getCallbackFromPointer(userData); - - ScopedGError error; - GVariant* result = g_dbus_connection_call_finish(connection, asyncResult, &error); - if (error) { - error.strip(); - LOGE("Call method failed; " << error); - } - AsyncMethodCallResultImpl asyncMethodCallResult(result, error); - if (callback) { - callback(asyncMethodCallResult); - } -} - - -} // namespace dbus -} // namespace security_containers diff --git a/common/dbus/connection.hpp b/common/dbus/connection.hpp deleted file mode 100644 index 9ac87de..0000000 --- a/common/dbus/connection.hpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Dbus connection class - */ - -#ifndef COMMON_DBUS_CONNECTION_HPP -#define COMMON_DBUS_CONNECTION_HPP - -#include "utils/callback-guard.hpp" - -#include -#include -#include -#include - - -namespace security_containers { -namespace dbus { - - -typedef std::unique_ptr GVariantPtr; - -/** - * An interface used to set a result to a method call. - */ -class MethodResultBuilder { -public: - typedef std::shared_ptr Pointer; - - virtual ~MethodResultBuilder() {} - virtual void set(GVariant* parameters) = 0; - virtual void setVoid() = 0; - virtual void setError(const std::string& name, const std::string& message) = 0; -}; - -/** - * An interface used to get result from async response. - */ -class AsyncMethodCallResult { -public: - virtual ~AsyncMethodCallResult() {} - virtual GVariant* get() = 0; // throws DbusException on error -}; - -/** - * Dbus connection. - * Provides a functionality that allows to call dbus methods, - * register dbus interfaces, etc. - * - * TODO divide to interface and implementation header - */ -class DbusConnection { -public: - typedef std::unique_ptr Pointer; - - typedef std::function VoidCallback; - - typedef std::function MethodCallCallback; - - typedef std::function SignalCallback; - - typedef std::function AsyncMethodCallCallback; - - /** - * Creates a connection to the dbus with given address. - */ - static Pointer create(const std::string& address); - - /** - * Creates a connection to the system dbus. - */ - static Pointer createSystem(); - - ~DbusConnection(); - - /** - * Sets a name to the dbus connection. - * It allows other client to call methods using this name. - */ - void setName(const std::string& name, - const VoidCallback& onNameAcquired, - const VoidCallback& onNameLost); - - /** - * Emits dbus signal. - */ - void emitSignal(const std::string& objectPath, - const std::string& interface, - const std::string& name, - GVariant* parameters); - - /** - * Subscribes to a signal. - * Empty sender means subscribe to all signals - */ - void signalSubscribe(const SignalCallback& callback, const std::string& senderBusName); - - /** - * Registers an object with given definition. - * Api calls will be handled by given callback. - */ - void registerObject(const std::string& objectPath, - const std::string& objectDefinitionXml, - const MethodCallCallback& callback); - - /** - * Call a dbus method - */ - GVariantPtr callMethod(const std::string& busName, - const std::string& objectPath, - const std::string& interface, - const std::string& method, - GVariant* parameters, - const std::string& replyType); - - /** - * Async call a dbus method - */ - void callMethodAsync(const std::string& busName, - const std::string& objectPath, - const std::string& interface, - const std::string& method, - GVariant* parameters, - const std::string& replyType, - const AsyncMethodCallCallback& callback); - - /** - * Returns an xml with meta description of specified dbus object. - */ - std::string introspect(const std::string& busName, const std::string& objectPath); - -private: - struct NameCallbacks { - VoidCallback nameAcquired; - VoidCallback nameLost; - - NameCallbacks(const VoidCallback& acquired, const VoidCallback& lost) - : nameAcquired(acquired), nameLost(lost) {} - }; - - utils::CallbackGuard mGuard; - GDBusConnection* mConnection; - guint mNameId; - - DbusConnection(const std::string& address); - - static void onNameAcquired(GDBusConnection* connection, const gchar* name, gpointer userData); - static void onNameLost(GDBusConnection* connection, const gchar* name, gpointer userData); - static void onSignal(GDBusConnection* connection, - const gchar* sender, - const gchar* object, - const gchar* interface, - const gchar* name, - GVariant* parameters, - gpointer userData); - static void onMethodCall(GDBusConnection* connection, - const gchar* sender, - const gchar* objectPath, - const gchar* interface, - const gchar* method, - GVariant* parameters, - GDBusMethodInvocation* invocation, - gpointer userData); - static void onAsyncReady(GObject* source, - GAsyncResult* asyncResult, - gpointer userData); -}; - - -} // namespace dbus -} // namespace security_containers - - -#endif // COMMON_DBUS_CONNECTION_HPP diff --git a/common/dbus/exception.hpp b/common/dbus/exception.hpp deleted file mode 100644 index 32cf87c..0000000 --- a/common/dbus/exception.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Piotr Bartosiewicz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Dbus exceptions - */ - - -#ifndef COMMON_DBUS_EXCEPTION_HPP -#define COMMON_DBUS_EXCEPTION_HPP - -#include "base-exception.hpp" - - -namespace security_containers { -namespace dbus { - - -/** - * Base class for dbus exceptions - */ -struct DbusException: public SecurityContainersException { - - DbusException(const std::string& error = "") : SecurityContainersException(error) {} -}; - -/** - * Dbus IO exception (connection failed, connection lost, etc) - */ -struct DbusIOException: public DbusException { - - DbusIOException(const std::string& error = "") : DbusException(error) {} -}; - -/** - * Dbus operation failed exception - */ -struct DbusOperationException: public DbusException { - - DbusOperationException(const std::string& error = "") : DbusException(error) {} -}; - -/** - * Dbus custom exception triggered by user logic - */ -struct DbusCustomException: public DbusException { - - DbusCustomException(const std::string& error = "") : DbusException(error) {} -}; - -/** - * Dbus invalid argument exception - */ -struct DbusInvalidArgumentException: public DbusException { - - DbusInvalidArgumentException(const std::string& error = "") : DbusException(error) {} -}; - - -} // namespace dbus -} // namespace security_containers - - -#endif // COMMON_DBUS_EXCEPTION_HPP diff --git a/common/libvirt/connection.cpp b/common/libvirt/connection.cpp index 12c906d..2fdaaa9 100644 --- a/common/libvirt/connection.cpp +++ b/common/libvirt/connection.cpp @@ -23,7 +23,7 @@ */ #include "config.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "libvirt/helpers.hpp" #include "libvirt/connection.hpp" #include "libvirt/exception.hpp" diff --git a/common/libvirt/domain.cpp b/common/libvirt/domain.cpp index 8b6bb98..d9e4217 100644 --- a/common/libvirt/domain.cpp +++ b/common/libvirt/domain.cpp @@ -23,7 +23,7 @@ */ #include "config.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "libvirt/domain.hpp" #include "libvirt/helpers.hpp" #include "libvirt/exception.hpp" diff --git a/common/libvirt/helpers.cpp b/common/libvirt/helpers.cpp index 7948a6a..8b096bb 100644 --- a/common/libvirt/helpers.cpp +++ b/common/libvirt/helpers.cpp @@ -24,7 +24,7 @@ #include "config.hpp" #include "libvirt/helpers.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include diff --git a/common/libvirt/network.cpp b/common/libvirt/network.cpp index 5384d9f..486ae63 100644 --- a/common/libvirt/network.cpp +++ b/common/libvirt/network.cpp @@ -24,7 +24,7 @@ #include "config.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "libvirt/network.hpp" #include "libvirt/helpers.hpp" #include "libvirt/exception.hpp" diff --git a/common/log/backend-journal.cpp b/common/log/backend-journal.cpp deleted file mode 100644 index 859d546..0000000 --- a/common/log/backend-journal.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Systemd journal backend for logger - */ - -#include "config.hpp" -#include "log/backend-journal.hpp" - -#define SD_JOURNAL_SUPPRESS_LOCATION -#include - -namespace security_containers { -namespace log { - -namespace { - -inline int toJournalPriority(LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return LOG_ERR; // 3 - case LogLevel::WARN: - return LOG_WARNING; // 4 - case LogLevel::INFO: - return LOG_INFO; // 6 - case LogLevel::DEBUG: - return LOG_DEBUG; // 7 - case LogLevel::TRACE: - return LOG_DEBUG; // 7 - default: - return LOG_DEBUG; - } -} - -} // namespace - -void SystemdJournalBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) -{ - sd_journal_send("PRIORITY=%d", toJournalPriority(logLevel), - "CODE_FILE=%s", file.c_str(), - "CODE_LINE=%d", line, - "CODE_FUNC=%s", func.c_str(), - "MESSAGE=%s", message.c_str(), - NULL); -} - -} // namespace log -} // namespace security_containers - diff --git a/common/log/backend-journal.hpp b/common/log/backend-journal.hpp deleted file mode 100644 index f040d9a..0000000 --- a/common/log/backend-journal.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Systemd journal backend for logger - */ - -#ifndef COMMON_LOG_BACKEND_JOURNAL_HPP -#define COMMON_LOG_BACKEND_JOURNAL_HPP - -#include "log/backend.hpp" - - -namespace security_containers { -namespace log { - - -/** - systemd journal logging backend - */ -class SystemdJournalBackend : public LogBackend { -public: - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -}; - - -} // namespace log -} // namespace security_containers - - -#endif // COMMON_LOG_BACKEND_JOURNAL_HPP diff --git a/common/log/backend-null.hpp b/common/log/backend-null.hpp deleted file mode 100644 index 7a26344..0000000 --- a/common/log/backend-null.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Pawel Broda - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Pawel Broda (p.broda@partner.samsung.com) - * @brief Null backend for logger - */ - - -#ifndef COMMON_LOG_BACKEND_NULL_HPP -#define COMMON_LOG_BACKEND_NULL_HPP - -#include "log/backend.hpp" - - -namespace security_containers { -namespace log { - - -/** - Null logging backend - */ -class NullLogger : public LogBackend { -public: - void log(LogLevel /*logLevel*/, - const std::string& /*file*/, - const unsigned int& /*line*/, - const std::string& /*func*/, - const std::string& /*message*/) override {} -}; - - -} // namespace log -} // namespace security_containers - - -#endif // COMMON_LOG_BACKEND_NULL_HPP diff --git a/common/log/backend-stderr.cpp b/common/log/backend-stderr.cpp deleted file mode 100644 index 471106c..0000000 --- a/common/log/backend-stderr.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Pawel Broda - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Pawel Broda (p.broda@partner.samsung.com) - * @brief Stderr backend for logger - */ - -#include "config.hpp" -#include "log/backend-stderr.hpp" -#include "log/formatter.hpp" - -#include - -namespace security_containers { -namespace log { - -void StderrBackend::log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) -{ - typedef boost::char_separator charSeparator; - typedef boost::tokenizer tokenizer; - - // example log string - // 06:52:35.123 [ERROR] src/util/fs.cpp:43 readFileContent: /file/file.txt is missing - - const std::string logColor = LogFormatter::getConsoleColor(logLevel); - const std::string defaultColor = LogFormatter::getDefaultConsoleColor(); - const std::string header = LogFormatter::getHeader(logLevel, file, line, func); - tokenizer tokens(message, charSeparator("\n")); - for (const auto& messageLine : tokens) { - if (!messageLine.empty()) { - fprintf(stderr, - "%s%s%s%s\n", - logColor.c_str(), - header.c_str(), - messageLine.c_str(), - defaultColor.c_str()); - } - } -} - - -} // namespace log -} // namespace security_containers - diff --git a/common/log/backend-stderr.hpp b/common/log/backend-stderr.hpp deleted file mode 100644 index c60d523..0000000 --- a/common/log/backend-stderr.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Pawel Broda - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Pawel Broda (p.broda@partner.samsung.com) - * @brief Stderr backend for logger - */ - -#ifndef COMMON_LOG_BACKEND_STDERR_HPP -#define COMMON_LOG_BACKEND_STDERR_HPP - -#include "log/backend.hpp" - - -namespace security_containers { -namespace log { - - -/** - Stderr logging backend - */ -class StderrBackend : public LogBackend { -public: - void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) override; -}; - - -} // namespace log -} // namespace security_containers - - -#endif // COMMON_LOG_BACKEND_STDERR_HPP diff --git a/common/log/backend.hpp b/common/log/backend.hpp deleted file mode 100644 index adad533..0000000 --- a/common/log/backend.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Pawel Broda - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Pawel Broda (p.broda@partner.samsung.com) - * @brief Logging backend - */ - - -#ifndef COMMON_LOG_BACKEND_HPP -#define COMMON_LOG_BACKEND_HPP - -#include "log/level.hpp" - -#include - -namespace security_containers { -namespace log { - - -/** - Abstract class for logger - */ -class LogBackend { -public: - virtual void log(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func, - const std::string& message) = 0; - virtual ~LogBackend() {} -}; - - -} // namespace log -} // namespace security_containers - - -#endif // COMMON_LOG_BACKEND_HPP diff --git a/common/log/ccolor.cpp b/common/log/ccolor.cpp deleted file mode 100644 index 128f11f..0000000 --- a/common/log/ccolor.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Console color for StderrBackend logger - */ - -#include "config.hpp" -#include "log/ccolor.hpp" - -#include - -namespace security_containers { -namespace log { - -std::string getConsoleEscapeSequence(Attributes attr, Color color) -{ - char command[10]; - - // Command is the control command to the terminal - snprintf(command, sizeof(command), "%c[%d;%dm", 0x1B, attr, color); - return std::string(command); -} - -} // namespace log -} // namespace security_containers - diff --git a/common/log/ccolor.hpp b/common/log/ccolor.hpp deleted file mode 100644 index dc37458..0000000 --- a/common/log/ccolor.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Console color for StderrBackend logger - */ - -#ifndef COMMON_LOG_CCOLOR_HPP -#define COMMON_LOG_CCOLOR_HPP - -#include - -namespace security_containers { -namespace log { - -enum class Color : unsigned int { - DEFAULT = 0, - BLACK = 90, - RED = 91, - GREEN = 92, - YELLOW = 93, - BLUE = 94, - MAGENTA = 95, - CYAN = 96, - WHITE = 97 -}; - -enum class Attributes : unsigned int { - DEFAULT = 0, - BOLD = 1 -}; - -std::string getConsoleEscapeSequence(Attributes attr, Color color); - -} // namespace log -} // namespace security_containers - -#endif // COMMON_LOG_CCOLOR_HPP - diff --git a/common/log/formatter.cpp b/common/log/formatter.cpp deleted file mode 100644 index 100a8eb..0000000 --- a/common/log/formatter.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Helper formatter for logger - */ - -#include "config.hpp" -#include "log/formatter.hpp" -#include "log/ccolor.hpp" - -#include -#include -#include -#include -#include -#include - -namespace security_containers { -namespace log { - -namespace { - -const int TIME_COLUMN_LENGTH = 12; -const int SEVERITY_COLUMN_LENGTH = 8; -const int THREAD_COLUMN_LENGTH = 3; -const int FILE_COLUMN_LENGTH = 60; - -std::atomic gNextThreadId(1); -thread_local unsigned int gThisThreadId(0); - -} // namespace - -unsigned int LogFormatter::getCurrentThread(void) -{ - unsigned int id = gThisThreadId; - if (id == 0) { - gThisThreadId = id = gNextThreadId++; - } - - return id; -} - -std::string LogFormatter::getCurrentTime(void) -{ - char time[TIME_COLUMN_LENGTH + 1]; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm* tm = localtime(&tv.tv_sec); - snprintf(time, - sizeof(time), - "%02d:%02d:%02d.%03d", - tm->tm_hour, - tm->tm_min, - tm->tm_sec, - int(tv.tv_usec / 1000)); - - return std::string(time); -} - -std::string LogFormatter::getConsoleColor(LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return getConsoleEscapeSequence(Attributes::BOLD, Color::RED); - case LogLevel::WARN: - return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW); - case LogLevel::INFO: - return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE); - case LogLevel::DEBUG: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN); - case LogLevel::TRACE: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK); - default: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); - } -} - -std::string LogFormatter::getDefaultConsoleColor(void) -{ - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); -} - -std::string LogFormatter::stripProjectDir(const std::string& file) -{ - const std::string SOURCE_DIR = PROJECT_SOURCE_DIR "/"; - // it will work until someone use in cmake FILE(GLOB ... RELATIVE ...) - assert(0 == file.compare(0, SOURCE_DIR.size(), SOURCE_DIR)); - return file.substr(SOURCE_DIR.size()); -} - -std::string LogFormatter::getHeader(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func) -{ - std::ostringstream logLine; - logLine << getCurrentTime() << ' ' - << std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']' - << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": " - << std::left << std::setw(FILE_COLUMN_LENGTH) - << file + ':' + std::to_string(line) + ' ' + func + ':'; - return logLine.str(); -} - -} // namespace log -} // namespace security_containers diff --git a/common/log/formatter.hpp b/common/log/formatter.hpp deleted file mode 100644 index 7f83ebe..0000000 --- a/common/log/formatter.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Helper formatter for logger - */ - -#ifndef COMMON_LOG_FORMATTER_HPP -#define COMMON_LOG_FORMATTER_HPP - -#include "log/level.hpp" - -#include - -namespace security_containers { -namespace log { - -class LogFormatter { -public: - static unsigned int getCurrentThread(void); - static std::string getCurrentTime(void); - static std::string getConsoleColor(LogLevel logLevel); - static std::string getDefaultConsoleColor(void); - static std::string stripProjectDir(const std::string& file); - static std::string getHeader(LogLevel logLevel, - const std::string& file, - const unsigned int& line, - const std::string& func); -}; - -} // namespace log -} // namespace security_containers - -#endif // COMMON_LOG_FORMATTER_HPP - diff --git a/common/log/level.cpp b/common/log/level.cpp deleted file mode 100644 index 3897726..0000000 --- a/common/log/level.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Jan Olszak - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Jan Olszak (j.olszak@samsung.com) - * @brief Functions to handle LogLevel - */ - -#include "config.hpp" - -#include "log/level.hpp" - -#include -#include - -namespace security_containers { -namespace log { - -LogLevel parseLogLevel(const std::string& level) -{ - if (boost::iequals(level, "ERROR")) { - return LogLevel::ERROR; - } else if (boost::iequals(level, "WARN")) { - return LogLevel::WARN; - } else if (boost::iequals(level, "INFO")) { - return LogLevel::INFO; - } else if (boost::iequals(level, "DEBUG")) { - return LogLevel::DEBUG; - } else if (boost::iequals(level, "TRACE")) { - return LogLevel::TRACE; - } else { - throw std::runtime_error("Invalid LogLevel to parse"); - } -} - -std::string toString(const LogLevel logLevel) -{ - switch (logLevel) { - case LogLevel::ERROR: - return "ERROR"; - case LogLevel::WARN: - return "WARN"; - case LogLevel::INFO: - return "INFO"; - case LogLevel::DEBUG: - return "DEBUG"; - case LogLevel::TRACE: - return "TRACE"; - default: - return "UNKNOWN"; - } -} -} // namespace log -} // namespace security_containers diff --git a/common/log/level.hpp b/common/log/level.hpp deleted file mode 100644 index 6a54cda..0000000 --- a/common/log/level.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Dariusz Michaluk (d.michaluk@samsung.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief LogLevel - */ - -#ifndef COMMON_LOG_LEVEL_HPP -#define COMMON_LOG_LEVEL_HPP - -#include - - -namespace security_containers { -namespace log { - -enum class LogLevel { - TRACE, - DEBUG, - INFO, - WARN, - ERROR -}; - -/** - * @param logLevel LogLevel - * @return std::sting representation of the LogLevel value - */ -std::string toString(const LogLevel logLevel); - -/** - * @param level string representation of log level - * @return parsed LogLevel value - */ -LogLevel parseLogLevel(const std::string& level); - - -} // namespace log -} // namespace security_containers - -#endif // COMMON_LOG_LEVEL_HPP diff --git a/common/log/logger.cpp b/common/log/logger.cpp deleted file mode 100644 index 83298ed..0000000 --- a/common/log/logger.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Pawel Broda - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Pawel Broda (p.broda@partner.samsung.com) - * @brief Logger - */ - -#include "config.hpp" -#include "log/logger.hpp" -#include "log/formatter.hpp" -#include "log/backend-null.hpp" - -#include -#include - -namespace security_containers { -namespace log { - - -namespace { - -volatile LogLevel gLogLevel = LogLevel::DEBUG; -std::unique_ptr gLogBackendPtr(new NullLogger()); -std::mutex gLogMutex; - -} // namespace - -Logger::Logger(LogLevel logLevel, - const std::string& file, - const unsigned int line, - const std::string& func) - : mLogLevel(logLevel), - mFile(LogFormatter::stripProjectDir(file)), - mLine(line), - mFunc(func) -{ - -} - -void Logger::logMessage(const std::string& message) -{ - std::unique_lock lock(gLogMutex); - gLogBackendPtr->log(mLogLevel, mFile, mLine, mFunc, message); -} - -void Logger::setLogLevel(const LogLevel level) -{ - gLogLevel = level; -} - -void Logger::setLogLevel(const std::string& level) -{ - gLogLevel = parseLogLevel(level); -} - -LogLevel Logger::getLogLevel(void) -{ - return gLogLevel; -} - -void Logger::setLogBackend(LogBackend* pBackend) -{ - std::unique_lock lock(gLogMutex); - gLogBackendPtr.reset(pBackend); -} - -} // namespace log -} // namespace security_containers - diff --git a/common/log/logger.hpp b/common/log/logger.hpp deleted file mode 100644 index 45c5f26..0000000 --- a/common/log/logger.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: Jan Olszak - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -/** - * @file - * @author Jan Olszak (j.olszak@samsung.com) - * @brief Logger - */ - - -#ifndef COMMON_LOG_LOGGER_HPP -#define COMMON_LOG_LOGGER_HPP - -#include "log/level.hpp" - -#include -#include - - -namespace security_containers { -namespace log { - -class LogBackend; - -class Logger { -public: - Logger(LogLevel logLevel, - const std::string& file, - const unsigned int line, - const std::string& func); - - void logMessage(const std::string& message); - - static void setLogLevel(const LogLevel level); - static void setLogLevel(const std::string& level); - static LogLevel getLogLevel(void); - static void setLogBackend(LogBackend* pBackend); - -private: - LogLevel mLogLevel; - std::string mFile; - unsigned int mLine; - std::string mFunc; -}; - -} // namespace log -} // namespace security_containers - - -#define LOG(SEVERITY, MESSAGE) \ - do { \ - if (security_containers::log::Logger::getLogLevel() <= \ - security_containers::log::LogLevel::SEVERITY) { \ - std::ostringstream messageStream__; \ - messageStream__ << MESSAGE; \ - security_containers::log::Logger logger(security_containers::log::LogLevel::SEVERITY, \ - __FILE__, \ - __LINE__, \ - __func__); \ - logger.logMessage(messageStream__.str()); \ - } \ - } while(0) - -#define LOGE(MESSAGE) LOG(ERROR, MESSAGE) -#define LOGW(MESSAGE) LOG(WARN, MESSAGE) -#define LOGI(MESSAGE) LOG(INFO, MESSAGE) -#define LOGD(MESSAGE) LOG(DEBUG, MESSAGE) -#define LOGT(MESSAGE) LOG(TRACE, MESSAGE) - - -#endif // COMMON_LOG_LOGGER_HPP - diff --git a/common/utils/callback-guard.cpp b/common/utils/callback-guard.cpp index 3a35098..d8ee57c 100644 --- a/common/utils/callback-guard.cpp +++ b/common/utils/callback-guard.cpp @@ -24,7 +24,7 @@ #include "config.hpp" #include "utils/callback-guard.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include diff --git a/common/utils/environment.cpp b/common/utils/environment.cpp index b74983d..70ef27c 100644 --- a/common/utils/environment.cpp +++ b/common/utils/environment.cpp @@ -25,7 +25,7 @@ #include "config.hpp" #include "utils/environment.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index 354e726..d663831 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -23,7 +23,7 @@ */ #include "config.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/fs.hpp" #include "utils/paths.hpp" #include "utils/exception.hpp" diff --git a/container-daemon/CMakeLists.txt b/container-daemon/CMakeLists.txt index 238af6f..c264a38 100644 --- a/container-daemon/CMakeLists.txt +++ b/container-daemon/CMakeLists.txt @@ -31,7 +31,8 @@ ADD_EXECUTABLE(${CONTAINER_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS program_options system filesystem) -PKG_CHECK_MODULES(CONTAINER_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal libcap-ng) +PKG_CHECK_MODULES(CONTAINER_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal libcap-ng + libLogger libSimpleDbus libConfig) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${CONTAINER_DAEMON_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${CONTAINER_DAEMON_CODENAME} ${CONTAINER_DAEMON_DEPS_LIBRARIES} ${Boost_LIBRARIES}) diff --git a/container-daemon/daemon-connection.cpp b/container-daemon/daemon-connection.cpp index 0eb6636..7f4d6b7 100644 --- a/container-daemon/daemon-connection.cpp +++ b/container-daemon/daemon-connection.cpp @@ -28,7 +28,7 @@ #include "daemon-dbus-definitions.hpp" #include "exception.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" namespace security_containers { diff --git a/container-daemon/daemon.cpp b/container-daemon/daemon.cpp index d79762f..6848a09 100644 --- a/container-daemon/daemon.cpp +++ b/container-daemon/daemon.cpp @@ -26,7 +26,7 @@ #include "daemon.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" namespace security_containers { diff --git a/container-daemon/main.cpp b/container-daemon/main.cpp index 8dcdbad..fde059a 100644 --- a/container-daemon/main.cpp +++ b/container-daemon/main.cpp @@ -33,15 +33,15 @@ #include "exception.hpp" #include "runner.hpp" -#include "log/logger.hpp" -#include "log/backend-stderr.hpp" -#include "log/backend-journal.hpp" +#include "logger/logger.hpp" +#include "logger/backend-stderr.hpp" +#include "logger/backend-journal.hpp" #include "utils/typeinfo.hpp" #include #include -using namespace security_containers::log; +using namespace logger; using namespace security_containers; namespace po = boost::program_options; diff --git a/container-daemon/runner.cpp b/container-daemon/runner.cpp index 13d3f21..7b5c93f 100644 --- a/container-daemon/runner.cpp +++ b/container-daemon/runner.cpp @@ -27,7 +27,7 @@ #include "runner.hpp" #include "daemon.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/glib-loop.hpp" #include "utils/latch.hpp" diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index af4751c..f7a1bdb 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -18,6 +18,9 @@ BuildRequires: boost-devel BuildRequires: libvirt-devel BuildRequires: libjson-devel >= 0.10 BuildRequires: libcap-ng-devel +BuildRequires: pkgconfig(libConfig) +BuildRequires: pkgconfig(libLogger) +BuildRequires: pkgconfig(libSimpleDbus) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libsystemd-journal) BuildRequires: pkgconfig(libvirt-glib-1.0) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 1e639cd..3293307 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -30,7 +30,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex) PKG_CHECK_MODULES(SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 libsystemd-journal - libcap-ng) + libcap-ng libLogger libSimpleDbus libConfig) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) diff --git a/server/container-admin.cpp b/server/container-admin.cpp index b624817..805e9c1 100644 --- a/server/container-admin.cpp +++ b/server/container-admin.cpp @@ -28,7 +28,7 @@ #include "exception.hpp" #include "libvirt/helpers.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/fs.hpp" #include "utils/latch.hpp" #include "utils/callback-wrapper.hpp" diff --git a/server/container-connection-transport.cpp b/server/container-connection-transport.cpp index 9b8848d..b5bcfb5 100644 --- a/server/container-connection-transport.cpp +++ b/server/container-connection-transport.cpp @@ -29,7 +29,7 @@ #include "utils/file-wait.hpp" #include "utils/fs.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include diff --git a/server/container-connection.cpp b/server/container-connection.cpp index 0e96bb2..d3098aa 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -30,7 +30,7 @@ // TODO: Switch to real power-manager dbus defs when they will be implemented in power-manager #include "fake-power-manager-dbus-definitions.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" namespace security_containers { diff --git a/server/container.cpp b/server/container.cpp index 4284fec..6fcaf77 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -25,8 +25,9 @@ #include "config.hpp" #include "container.hpp" +#include "base-exception.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/paths.hpp" #include "config/manager.hpp" diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 012a8f7..90a6cfc 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -32,9 +32,10 @@ #include "exception.hpp" #include "utils/paths.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "config/manager.hpp" #include "dbus/exception.hpp" +#include "utils/fs.hpp" #include #include diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 83ba8f8..ae32de2 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -28,7 +28,7 @@ #include "host-dbus-definitions.hpp" #include "exception.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" namespace security_containers { diff --git a/server/input-monitor.cpp b/server/input-monitor.cpp index 13025a5..76dff29 100644 --- a/server/input-monitor.cpp +++ b/server/input-monitor.cpp @@ -28,7 +28,7 @@ #include "input-monitor.hpp" #include "exception.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/exception.hpp" #include "utils/fs.hpp" #include "utils/callback-wrapper.hpp" diff --git a/server/main.cpp b/server/main.cpp index d84a850..bf3da84 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -33,15 +33,15 @@ #include "exception.hpp" #include "server.hpp" -#include "log/logger.hpp" -#include "log/backend-stderr.hpp" -#include "log/backend-journal.hpp" +#include "logger/logger.hpp" +#include "logger/backend-stderr.hpp" +#include "logger/backend-journal.hpp" #include "utils/typeinfo.hpp" #include #include -using namespace security_containers::log; +using namespace logger; using namespace security_containers; namespace po = boost::program_options; diff --git a/server/network-admin.cpp b/server/network-admin.cpp index 38f9b07..763dec0 100644 --- a/server/network-admin.cpp +++ b/server/network-admin.cpp @@ -28,7 +28,7 @@ #include "exception.hpp" #include "libvirt/helpers.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/fs.hpp" #include diff --git a/server/server.cpp b/server/server.cpp index c2fae7d..5c3420d 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -29,9 +29,10 @@ #include "exception.hpp" #include "config/manager.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include "utils/glib-loop.hpp" #include "utils/environment.hpp" +#include "utils/fs.hpp" #include #include diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 30d309b..a82075c 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -35,7 +35,7 @@ ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRC FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex) PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 - libsystemd-journal libcap-ng) + libsystemd-journal libcap-ng libLogger libSimpleDbus libConfig) INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES}) diff --git a/tests/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp index 5417e5f..7d304db 100644 --- a/tests/unit_tests/config/ut-configuration.cpp +++ b/tests/unit_tests/config/ut-configuration.cpp @@ -28,8 +28,7 @@ #include "config/fields.hpp" #include "config/manager.hpp" -using namespace security_containers; -using namespace security_containers::config; +using namespace config; BOOST_AUTO_TEST_SUITE(ConfigurationSuite) diff --git a/tests/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp index 3a77390..bdbda8b 100644 --- a/tests/unit_tests/dbus/test-server.cpp +++ b/tests/unit_tests/dbus/test-server.cpp @@ -29,7 +29,7 @@ #include "dbus/connection.hpp" #include "dbus/exception.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" namespace security_containers { diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 21be1e8..18d4f7b 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -35,7 +35,7 @@ #include "utils/file-wait.hpp" #include "utils/latch.hpp" #include "utils/fs.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_SUITE(DbusSuite) using namespace security_containers; using namespace security_containers::utils; -using namespace security_containers::dbus; +using namespace dbus; namespace { diff --git a/tests/unit_tests/log/ut-logger.cpp b/tests/unit_tests/log/ut-logger.cpp index b4aeb5d..e574505 100644 --- a/tests/unit_tests/log/ut-logger.cpp +++ b/tests/unit_tests/log/ut-logger.cpp @@ -25,16 +25,16 @@ #include "config.hpp" #include "ut.hpp" -#include "log/logger.hpp" -#include "log/formatter.hpp" -#include "log/backend.hpp" -#include "log/backend-stderr.hpp" +#include "logger/logger.hpp" +#include "logger/formatter.hpp" +#include "logger/backend.hpp" +#include "logger/backend-stderr.hpp" #include BOOST_AUTO_TEST_SUITE(LogSuite) -using namespace security_containers::log; +using namespace logger; namespace { diff --git a/tests/unit_tests/server/ut-container-connection.cpp b/tests/unit_tests/server/ut-container-connection.cpp index 29dd310..1a2d153 100644 --- a/tests/unit_tests/server/ut-container-connection.cpp +++ b/tests/unit_tests/server/ut-container-connection.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_SUITE(ContainerConnectionSuite) using namespace security_containers; using namespace security_containers::utils; -using namespace security_containers::dbus; +using namespace dbus; namespace { diff --git a/tests/unit_tests/server/ut-container.cpp b/tests/unit_tests/server/ut-container.cpp index 7b65c95..e636276 100644 --- a/tests/unit_tests/server/ut-container.cpp +++ b/tests/unit_tests/server/ut-container.cpp @@ -40,7 +40,7 @@ using namespace security_containers; -using namespace security_containers::config; +using namespace config; namespace { diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index b3ce809..e8dc5de 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -52,9 +52,9 @@ #include using namespace security_containers; -using namespace security_containers::config; +using namespace config; using namespace security_containers::utils; -using namespace security_containers::dbus; +using namespace dbus; namespace { @@ -332,7 +332,7 @@ std::function expectedMessage(const std::string& me } struct Fixture { - utils::ScopedGlibLoop mLoop; + security_containers::utils::ScopedGlibLoop mLoop; }; } // namespace diff --git a/tests/unit_tests/server/ut-server.cpp b/tests/unit_tests/server/ut-server.cpp index d7393b7..74bcede 100644 --- a/tests/unit_tests/server/ut-server.cpp +++ b/tests/unit_tests/server/ut-server.cpp @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_SUITE(ServerSuite) using namespace security_containers; -using namespace security_containers::config; +using namespace config; const std::string TEST_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-server/test-daemon.conf"; const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-server/buggy-daemon.conf"; diff --git a/tests/unit_tests/ut.cpp b/tests/unit_tests/ut.cpp index de98558..194dc9e 100644 --- a/tests/unit_tests/ut.cpp +++ b/tests/unit_tests/ut.cpp @@ -25,14 +25,14 @@ #include "config.hpp" -#include "log/logger.hpp" -#include "log/backend-stderr.hpp" +#include "logger/logger.hpp" +#include "logger/backend-stderr.hpp" #include using namespace boost::unit_test; -using namespace security_containers::log; +using namespace logger; test_suite* init_unit_test_suite(int /*argc*/, char** /*argv*/) { diff --git a/tests/unit_tests/utils/scoped-daemon.cpp b/tests/unit_tests/utils/scoped-daemon.cpp index 077e19a..21fea83 100644 --- a/tests/unit_tests/utils/scoped-daemon.cpp +++ b/tests/unit_tests/utils/scoped-daemon.cpp @@ -26,7 +26,7 @@ #include "utils/scoped-daemon.hpp" -#include "log/logger.hpp" +#include "logger/logger.hpp" #include #include -- 2.7.4 From 33c6ad7cbdfe563979889b201f3397f7e38ed60b Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 5 Aug 2014 18:00:00 +0200 Subject: [PATCH 16/16] Tests of the dynamic configuration in libConfig [Bug/Feature] Dynamic configuration stored in a database [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I112701773ec555bca0521871e2066d84d727a00b --- packaging/security-containers.spec | 1 + tests/unit_tests/config/ut-kvstore.cpp | 178 +++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 tests/unit_tests/config/ut-kvstore.cpp diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index f7a1bdb..30914b0 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -24,6 +24,7 @@ BuildRequires: pkgconfig(libSimpleDbus) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libsystemd-journal) BuildRequires: pkgconfig(libvirt-glib-1.0) +BuildRequires: pkgconfig(sqlite3) Requires: libvirt-daemon >= 1.2.4 Requires(post): libcap-tools diff --git a/tests/unit_tests/config/ut-kvstore.cpp b/tests/unit_tests/config/ut-kvstore.cpp new file mode 100644 index 0000000..26abf76 --- /dev/null +++ b/tests/unit_tests/config/ut-kvstore.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Unit test of KVStore class + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "config/kvstore.hpp" +#include "config/exception.hpp" + +#include +#include + +using namespace config; +namespace fs = boost::filesystem; + +namespace { + +struct Fixture { + std::string dbPath; + KVStore c; + + Fixture() + : dbPath(fs::unique_path("/tmp/kvstore-%%%%.db3").string()), + c(dbPath) + { + } + ~Fixture() + { + fs::remove(dbPath); + } +}; +} // namespace + +BOOST_FIXTURE_TEST_SUITE(KVStoreSuite, Fixture) + +const std::string KEY = "KEY"; + +BOOST_AUTO_TEST_CASE(SimpleConstructorDestructorTest) +{ + const std::string dbPath = fs::unique_path("/tmp/kvstore-%%%%.db3").string(); + std::unique_ptr conPtr; + BOOST_REQUIRE_NO_THROW(conPtr.reset(new KVStore(dbPath))); + BOOST_CHECK(fs::exists(dbPath)); + BOOST_REQUIRE_NO_THROW(conPtr.reset(new KVStore(dbPath))); + BOOST_CHECK(fs::exists(dbPath)); + BOOST_REQUIRE_NO_THROW(conPtr.reset()); + BOOST_CHECK(fs::exists(dbPath)); + fs::remove(dbPath); +} + +BOOST_AUTO_TEST_CASE(SingleValueTest) +{ + // Set + BOOST_CHECK_NO_THROW(c.set(KEY, "A")); + BOOST_CHECK_EQUAL(c.get(KEY), "A"); + + // Update + BOOST_CHECK_NO_THROW(c.set(KEY, "B")); + BOOST_CHECK_EQUAL(c.get(KEY), "B"); + BOOST_CHECK_EQUAL(c.count(KEY), 1); + + // Remove + BOOST_CHECK_NO_THROW(c.remove(KEY)); + BOOST_CHECK_EQUAL(c.count(KEY), 0); + BOOST_CHECK_THROW(c.get(KEY), ConfigException); +} + +BOOST_AUTO_TEST_CASE(EscapedCharactersTest) +{ + // '*' ?' '[' ']' are escaped + // They shouldn't influence the internal implementation + std::string HARD_KEY = "[" + KEY; + BOOST_CHECK_NO_THROW(c.set(HARD_KEY, "A")); + BOOST_CHECK_NO_THROW(c.set(KEY, "B")); + BOOST_CHECK_EQUAL(c.count(HARD_KEY), 1); + BOOST_CHECK_EQUAL(c.count(KEY), 1); + BOOST_CHECK_EQUAL(c.size(), 2); + BOOST_CHECK_NO_THROW(c.clear()); + + HARD_KEY = "]" + KEY; + BOOST_CHECK_NO_THROW(c.set(HARD_KEY, "A")); + BOOST_CHECK_NO_THROW(c.set(KEY, "B")); + BOOST_CHECK_EQUAL(c.count(HARD_KEY), 1); + BOOST_CHECK_EQUAL(c.count(KEY), 1); + BOOST_CHECK_EQUAL(c.size(), 2); + BOOST_CHECK_NO_THROW(c.clear()); + + HARD_KEY = "?" + KEY; + BOOST_CHECK_NO_THROW(c.set(HARD_KEY, "A")); + BOOST_CHECK_NO_THROW(c.set(KEY, "B")); + BOOST_CHECK_EQUAL(c.count(HARD_KEY), 1); + BOOST_CHECK_EQUAL(c.count(KEY), 1); + BOOST_CHECK_EQUAL(c.size(), 2); + BOOST_CHECK_NO_THROW(c.clear()); + + HARD_KEY = "*" + KEY; + BOOST_CHECK_NO_THROW(c.set(HARD_KEY, "A")); + BOOST_CHECK_NO_THROW(c.set(KEY, "B")); + BOOST_CHECK_EQUAL(c.count(HARD_KEY), 1); + BOOST_CHECK_EQUAL(c.count(KEY), 1); + BOOST_CHECK_EQUAL(c.size(), 2); +} + +BOOST_AUTO_TEST_CASE(VectorOfValuesTest) +{ + std::vector AB = {"A", "B"}; + std::vector AC = {"A", "C"}; + std::vector ABC = {"A", "B", "C"}; + + // Set + BOOST_CHECK_NO_THROW(c.set(KEY, AB)); + BOOST_CHECK(c.list(KEY) == AB); + BOOST_CHECK_EQUAL(c.count(KEY), 2); + BOOST_CHECK_EQUAL(c.size(), 2); + + + // Update + BOOST_CHECK_NO_THROW(c.set(KEY, AC)); + BOOST_CHECK(c.list(KEY) == AC); + BOOST_CHECK_EQUAL(c.count(KEY), 2); + BOOST_CHECK_EQUAL(c.size(), 2); + + // Update + BOOST_CHECK_NO_THROW(c.set(KEY, ABC)); + BOOST_CHECK(c.list(KEY) == ABC); + BOOST_CHECK_EQUAL(c.count(KEY), 3); + BOOST_CHECK_EQUAL(c.size(), 3); + + // Update + BOOST_CHECK_NO_THROW(c.set(KEY, AC)); + BOOST_CHECK(c.list(KEY) == AC); + BOOST_CHECK_EQUAL(c.count(KEY), 2); + BOOST_CHECK_EQUAL(c.size(), 2); + + // Remove + BOOST_CHECK_NO_THROW(c.remove(KEY)); + BOOST_CHECK_EQUAL(c.count(KEY), 0); + BOOST_CHECK_EQUAL(c.size(), 0); + BOOST_CHECK_THROW(c.list(KEY), ConfigException); + BOOST_CHECK_THROW(c.get(KEY), ConfigException); +} + +BOOST_AUTO_TEST_CASE(ClearTest) +{ + BOOST_CHECK_NO_THROW(c.clear()); + + BOOST_CHECK_NO_THROW(c.set(KEY, {"A", "B"})); + BOOST_CHECK_NO_THROW(c.clear()); + BOOST_CHECK_EQUAL(c.size(), 0); + + BOOST_CHECK_NO_THROW(c.remove(KEY)); + BOOST_CHECK_THROW(c.list(KEY), ConfigException); + BOOST_CHECK_THROW(c.get(KEY), ConfigException); +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4