From 21fd6f9cc1f696893737980eb68014a606164acc Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 19 May 2014 13:17:47 +0200 Subject: [PATCH 01/16] Unit tests for ContainerAdmin using and testing the listeners [Bug/Feature] Revamped tests for ContainerAdmin. [Cause] N/A [Solution] They use and test Listeners. New test for the stop() procedure. [Verification] Built, installed and run tests. Change-Id: I76c0a3871298855b8cbdcddbd21e8421887d34ed Signed-off-by: Lukasz Pawelczyk --- server/container-admin.cpp | 2 +- unit_tests/server/configs/CMakeLists.txt | 2 + .../containers/test-no-shutdown.conf.in | 7 + .../libvirt-config/test-no-shutdown.xml | 12 ++ unit_tests/server/ut-container-admin.cpp | 161 +++++++++++++++++++-- unit_tests/server/ut-container.cpp | 2 +- unit_tests/server/ut-containers-manager.cpp | 2 +- 7 files changed, 170 insertions(+), 18 deletions(-) create mode 100644 unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in create mode 100644 unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml diff --git a/server/container-admin.cpp b/server/container-admin.cpp index 0365ba8..808bd76 100644 --- a/server/container-admin.cpp +++ b/server/container-admin.cpp @@ -187,7 +187,7 @@ void ContainerAdmin::stop() removeListener(id); if (!stopped) { - LOGD(mId << ": waiting for shutdown timed out, destroying"); + LOGW(mId << ": Gracefull shutdown timed out, the container is still running, destroying"); destroy(); } diff --git a/unit_tests/server/configs/CMakeLists.txt b/unit_tests/server/configs/CMakeLists.txt index e427b68..37a1a06 100644 --- a/unit_tests/server/configs/CMakeLists.txt +++ b/unit_tests/server/configs/CMakeLists.txt @@ -42,6 +42,8 @@ CONFIGURE_FILE(ut-container-admin/containers/buggy.conf.in ${CMAKE_BINARY_DIR}/ut-container-admin/containers/buggy.conf @ONLY) CONFIGURE_FILE(ut-container-admin/containers/test.conf.in ${CMAKE_BINARY_DIR}/ut-container-admin/containers/test.conf @ONLY) +CONFIGURE_FILE(ut-container-admin/containers/test-no-shutdown.conf.in + ${CMAKE_BINARY_DIR}/ut-container-admin/containers/test-no-shutdown.conf @ONLY) FILE(GLOB admin_container_CONF_GEN ${CMAKE_BINARY_DIR}/ut-container-admin/containers/*.conf) CONFIGURE_FILE(ut-container/libvirt-config/test-dbus.xml.in diff --git a/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in b/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in new file mode 100644 index 0000000..c1d89b9 --- /dev/null +++ b/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in @@ -0,0 +1,7 @@ +{ + "privilege" : 10, + "config" : "@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container-admin/libvirt-config/test-no-shutdown.xml", + "cpuQuotaForeground" : -1, + "cpuQuotaBackground" : 1000, + "runMountPoint" : "" +} diff --git a/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml b/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml new file mode 100644 index 0000000..609e155 --- /dev/null +++ b/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml @@ -0,0 +1,12 @@ + + ut-container-admin-test + f6924d8d-faa4-4cd3-8b47-383f45a4c0c8 + 102400 + + exe + /bin/sh + + + + + diff --git a/unit_tests/server/ut-container-admin.cpp b/unit_tests/server/ut-container-admin.cpp index 0d8cd23..5d4d09c 100644 --- a/unit_tests/server/ut-container-admin.cpp +++ b/unit_tests/server/ut-container-admin.cpp @@ -28,8 +28,10 @@ #include "container-admin.hpp" #include "exception.hpp" +#include "utils/latch.hpp" #include "utils/glib-loop.hpp" #include "utils/exception.hpp" +#include "utils/callback-guard.hpp" #include "libvirt/exception.hpp" #include @@ -38,16 +40,17 @@ #include -BOOST_AUTO_TEST_SUITE(ContainerAdminSuite) - using namespace security_containers; using namespace security_containers::config; namespace { const std::string TEST_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-container-admin/containers/test.conf"; +const std::string TEST_NO_SHUTDOWN_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-container-admin/containers/test-no-shutdown.conf"; const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-container-admin/containers/buggy.conf"; const std::string MISSING_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-container-admin/containers/missing.conf"; +const unsigned int WAIT_TIMEOUT = 5 * 1000; +const unsigned int WAIT_STOP_TIMEOUT = 15 * 1000; void ensureStarted() { @@ -55,9 +58,16 @@ void ensureStarted() std::this_thread::sleep_for(std::chrono::milliseconds(200)); } +struct Fixture { + utils::ScopedGlibLoop mLoop; + utils::CallbackGuard mGuard; +}; + } // namespace +BOOST_FIXTURE_TEST_SUITE(ContainerAdminSuite, Fixture) + BOOST_AUTO_TEST_CASE(ConstructorTest) { ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); @@ -85,63 +95,184 @@ BOOST_AUTO_TEST_CASE(MissingConfigTest) BOOST_AUTO_TEST_CASE(StartTest) { + utils::Latch booted; + ContainerAdmin::ListenerId id; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); + + ContainerAdmin::LifecycleListener bootedListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_STARTED && detail == VIR_DOMAIN_EVENT_STARTED_BOOTED) { + booted.set(); + } + }; + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(bootedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); + + BOOST_CHECK(booted.wait(WAIT_TIMEOUT)); BOOST_CHECK(ca.isRunning()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } -BOOST_AUTO_TEST_CASE(StopTest) +BOOST_AUTO_TEST_CASE(ShutdownTest) { - utils::ScopedGlibLoop loop; + utils::Latch shutdown; + ContainerAdmin::ListenerId id; + ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); + ContainerAdmin ca(config); + ContainerAdmin::LifecycleListener shutdownListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_STOPPED && detail == VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN) { + shutdown.set(); + } + }; + + BOOST_REQUIRE_NO_THROW(ca.start()); + ensureStarted(); + BOOST_REQUIRE(ca.isRunning()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(shutdownListener, mGuard.spawn())); + + BOOST_REQUIRE_NO_THROW(ca.shutdown()); + BOOST_CHECK(shutdown.wait(WAIT_TIMEOUT)); + BOOST_CHECK(!ca.isRunning()); + BOOST_CHECK(ca.isStopped()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); +} + +BOOST_AUTO_TEST_CASE(DestroyTest) +{ + utils::Latch destroyed; + ContainerAdmin::ListenerId id; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); + + ContainerAdmin::LifecycleListener destroyedListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_STOPPED && detail == VIR_DOMAIN_EVENT_STOPPED_DESTROYED) { + destroyed.set(); + } + }; + BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); - BOOST_CHECK(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(ca.stop()) + BOOST_REQUIRE(ca.isRunning()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(destroyedListener, mGuard.spawn())); + + BOOST_REQUIRE_NO_THROW(ca.destroy()); + BOOST_CHECK(destroyed.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isStopped()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } -BOOST_AUTO_TEST_CASE(ShutdownTest) +BOOST_AUTO_TEST_CASE(StopShutdownTest) { + utils::Latch shutdown; + ContainerAdmin::ListenerId id; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); - BOOST_REQUIRE_NO_THROW(ca.start()) + + ContainerAdmin::LifecycleListener shutdownListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_STOPPED && detail == VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN) { + shutdown.set(); + } + }; + + BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); - BOOST_CHECK(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(ca.shutdown()) - // TODO: For this simple configuration, the shutdown signal is ignored - // BOOST_CHECK(!ca.isRunning()); - // BOOST_CHECK(ca.isStopped()); + BOOST_REQUIRE(ca.isRunning()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(shutdownListener, mGuard.spawn())); + + BOOST_REQUIRE_NO_THROW(ca.stop()); + BOOST_CHECK(shutdown.wait(WAIT_TIMEOUT)); + BOOST_CHECK(!ca.isRunning()); + BOOST_CHECK(ca.isStopped()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); +} + +// This test needs to wait for a shutdown timer in stop() method. This takes 10s+. +BOOST_AUTO_TEST_CASE(StopDestroyTest) +{ + utils::Latch destroyed; + ContainerAdmin::ListenerId id; + ContainerConfig config; config.parseFile(TEST_NO_SHUTDOWN_CONFIG_PATH); + ContainerAdmin ca(config); + + ContainerAdmin::LifecycleListener destroyedListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_STOPPED && detail == VIR_DOMAIN_EVENT_STOPPED_DESTROYED) { + destroyed.set(); + } + }; + + BOOST_REQUIRE_NO_THROW(ca.start()); + ensureStarted(); + BOOST_REQUIRE(ca.isRunning()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(destroyedListener, mGuard.spawn())); + + BOOST_REQUIRE_NO_THROW(ca.stop()); + BOOST_CHECK(destroyed.wait(WAIT_STOP_TIMEOUT)); + BOOST_CHECK(!ca.isRunning()); + BOOST_CHECK(ca.isStopped()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(SuspendTest) { + utils::Latch paused; + ContainerAdmin::ListenerId id; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); + + ContainerAdmin::LifecycleListener pausedListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_SUSPENDED && detail == VIR_DOMAIN_EVENT_SUSPENDED_PAUSED) { + paused.set(); + } + }; + BOOST_REQUIRE_NO_THROW(ca.start()) ensureStarted(); - BOOST_CHECK(ca.isRunning()); + BOOST_REQUIRE(ca.isRunning()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(pausedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(ca.suspend()); + BOOST_CHECK(paused.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isPaused()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(ResumeTest) { + utils::Latch unpaused; + ContainerAdmin::ListenerId id; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); + + ContainerAdmin::LifecycleListener unpausedListener = [&](const int event, const int detail) { + if (event == VIR_DOMAIN_EVENT_RESUMED && detail == VIR_DOMAIN_EVENT_RESUMED_UNPAUSED) { + unpaused.set(); + } + }; + BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); + BOOST_REQUIRE(ca.isRunning()); BOOST_REQUIRE_NO_THROW(ca.suspend()) - BOOST_CHECK(ca.isPaused()); + BOOST_REQUIRE(ca.isPaused()); + BOOST_REQUIRE_NO_THROW(id = ca.registerListener(unpausedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(ca.resume()); + BOOST_CHECK(unpaused.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isPaused()); BOOST_CHECK(ca.isRunning()); + + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(SchedulerLevelTest) diff --git a/unit_tests/server/ut-container.cpp b/unit_tests/server/ut-container.cpp index ee71fe0..09aa059 100644 --- a/unit_tests/server/ut-container.cpp +++ b/unit_tests/server/ut-container.cpp @@ -46,7 +46,7 @@ const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-con const std::string MISSING_CONFIG_PATH = "/this/is/a/missing/file/path/config.conf"; struct Fixture { - utils::ScopedGlibLoop loop; + utils::ScopedGlibLoop mLoop; }; } // namespace diff --git a/unit_tests/server/ut-containers-manager.cpp b/unit_tests/server/ut-containers-manager.cpp index ab2bb75..b0a96db 100644 --- a/unit_tests/server/ut-containers-manager.cpp +++ b/unit_tests/server/ut-containers-manager.cpp @@ -45,7 +45,7 @@ const std::string BUGGY_FOREGROUND_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/se const std::string MISSING_CONFIG_PATH = "/this/is/a/missing/file/path/missing-daemon.conf"; struct Fixture { - utils::ScopedGlibLoop loop; + utils::ScopedGlibLoop mLoop; }; } // namespace -- 2.7.4 From 15d22682188bd8d8f01b15941370c8ca9f8843d4 Mon Sep 17 00:00:00 2001 From: Michal Witanowski Date: Wed, 16 Apr 2014 11:26:06 +0200 Subject: [PATCH 02/16] Make Security Containers Server a systemd service [Bug/Feature] Create systemd service for SCS launching. [Cause] N/A [Solution] * Needed configs and scripts have been written. * "post" and "postun" sections of the spec file have been filled. [Verification] Build and install on a target that has: * "business" and "private" root filesystems located at /opt/usr/containers/ * libvirtd running as systemd service After the installation, verify: 1. Stopping/starting the service via "systemctl stop/start security-containers.service". 2. Restarting the device (the containers should boot automatically). 3. Killing the Security Containers Server (for example: "kill -11 `pidof security-containers-server`") - the service should restart in this situation. 4. Uninstalling the Security Containers package - the containers should keep on running since next reboot. 5. Upgrading should send SIGUSR1 to the daemon (it will be handled by another commit). Change-Id: I514cc4c447e0f100022b80e2149fc3e228aa5f8a Signed-off-by: Michal Witanowski --- packaging/security-containers.spec | 32 +++++++++++++++++++++- server/configs/CMakeLists.txt | 5 +++- server/configs/systemd/security-containers.service | 13 +++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 server/configs/systemd/security-containers.service diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index c7e2df0..23b7bb3 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -28,6 +28,8 @@ between them. A process from inside a container can request a switch of context %dir /etc/security-containers/libvirt-config %config /etc/security-containers/daemon.conf %config /etc/security-containers/containers/*.conf +%{_unitdir}/security-containers.service +%{_unitdir}/multi-user.target.wants/security-containers.service %config %attr(400,root,root) /etc/security-containers/libvirt-config/*.xml /etc/security-containers/image-skel @@ -44,15 +46,43 @@ between them. A process from inside a container can request a switch of context %cmake . -DVERSION=%{version} \ -DCMAKE_BUILD_TYPE=%{build_type} \ - -DSCRIPT_INSTALL_DIR=%{script_dir} + -DSCRIPT_INSTALL_DIR=%{script_dir} \ + -DSYSTEMD_UNIT_DIR=%{_unitdir} make -k %{?jobs:-j%jobs} %install %make_install +mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants +ln -s ../security-containers.service %{buildroot}/%{_unitdir}/multi-user.target.wants/security-containers.service %clean rm -rf %{buildroot} +%post +# Refresh systemd services list after installation +if [ $1 == 1 ]; then + systemctl daemon-reload || : +fi + +%preun +# Stop the service before uninstall +if [ $1 == 0 ]; then + systemctl stop security-containers.service || : +fi + +%postun +# Refresh systemd services list after uninstall/upgrade +systemctl daemon-reload || : +if [ $1 -ge 1 ]; then + # TODO: at this point an appropriate notification should show up + eval `systemctl show security-containers --property=MainPID` + if [ -n "$MainPID" -a "$MainPID" != "0" ]; then + kill -USR1 $MainPID + fi + echo "Security Containers updated. Reboot is required for the changes to take effect..." +else + echo "Security Containers removed. Reboot is required for the changes to take effect..." +fi ## Client Package ############################################################## %package client diff --git a/server/configs/CMakeLists.txt b/server/configs/CMakeLists.txt index 11f258e..935cc2f 100644 --- a/server/configs/CMakeLists.txt +++ b/server/configs/CMakeLists.txt @@ -21,7 +21,7 @@ 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 ############################################################### INSTALL(FILES daemon.conf @@ -36,3 +36,6 @@ INSTALL(FILES ${container_CONF} INSTALL(FILES ${admin_CONF} DESTINATION ${SC_CONFIG_INSTALL_DIR}/libvirt-config) + +INSTALL(FILES ${SYSTEMD_SERVICES} + DESTINATION ${SYSTEMD_UNIT_DIR}) diff --git a/server/configs/systemd/security-containers.service b/server/configs/systemd/security-containers.service new file mode 100644 index 0000000..38e2fd7 --- /dev/null +++ b/server/configs/systemd/security-containers.service @@ -0,0 +1,13 @@ +[Unit] +Description=Security Containers Server +After=libvirtd.service +Requires=libvirtd.service + +[Service] +Type=simple +ExecStart=/usr/bin/security-containers-server +Restart=on-failure +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target -- 2.7.4 From 6e86807780dceb3b2978bf5169fc604b27748d45 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Mon, 28 Apr 2014 13:06:41 +0200 Subject: [PATCH 03/16] Reload SCS binary when updating security-containers [Feature] Reload SCS without turning containers off when binary is updated. [Cause] When updating SCS we don't want to restart containers, only SCS itself. [Solution] Add SIGUSR1 handling which will tell SCS to keep containers alive when exiting. Add check in ContainerConnectionTransport if containers are running to skip remount of tmpfs when it is not needed. [Verification] Build, install, reboot target. Test the following when SCS is running together with containers active: * Call "systemctl stop security-containers". SCS should turn off and containers should turn off as well. Call "systemctl start security-containers", SCS and containers should start up. * Simulate update by calling "kill -USR1 `pidof security-containers-server`". SCS should properly reload, however containers should stay on. (note - the best way to check it would be by verifying logs in journalctl). Change-Id: I3a6d0fb25a4579208ad0f6d0de00e2755548230e Signed-off-by: Lukasz Kostyra --- common/utils/fs.cpp | 19 ++++++++++++++ common/utils/fs.hpp | 5 ++++ server/container-admin.cpp | 26 +++++++++++++------- server/container-admin.hpp | 6 +++++ server/container-connection-transport.cpp | 32 +++++++++++++++++------- server/container-connection-transport.hpp | 6 +++++ server/container.cpp | 6 +++++ server/container.hpp | 8 ++++++ server/containers-manager.cpp | 23 +++++++++++++---- server/containers-manager.hpp | 6 +++++ server/main.cpp | 1 + server/server.cpp | 41 +++++++++++++++++++++++++++---- server/server.hpp | 7 +++++- 13 files changed, 157 insertions(+), 29 deletions(-) diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index b3e15cf..aac496f 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -117,6 +117,25 @@ bool umount(const std::string& path) return true; } +bool isMountPoint(const std::string& path, bool& result) +{ + struct stat stat, parentStat; + std::string parentPath = dirName(path); + + if (::stat(path.c_str(), &stat)) { + LOGD("Failed to get stat of " << path << ": " << strerror(errno)); + return false; + } + + if (::stat(parentPath.c_str(), &parentStat)) { + LOGD("Failed to get stat of " << parentPath << ": " << strerror(errno)); + return false; + } + + result = (stat.st_dev != parentStat.st_dev); + return true; +} + } // namespace utils } // namespace security_containers diff --git a/common/utils/fs.hpp b/common/utils/fs.hpp index 52273dd..95ce200 100644 --- a/common/utils/fs.hpp +++ b/common/utils/fs.hpp @@ -67,6 +67,11 @@ bool mountTmpfs(const std::string& path); */ bool umount(const std::string& path); +/** + * Check if given path is a mount point + */ +bool isMountPoint(const std::string& path, bool& result); + } // namespace utils } // namespace security_containers diff --git a/server/container-admin.cpp b/server/container-admin.cpp index 808bd76..657ab4f 100644 --- a/server/container-admin.cpp +++ b/server/container-admin.cpp @@ -69,6 +69,7 @@ ContainerAdmin::ContainerAdmin(ContainerConfig& config) : mConfig(config), mDom(utils::readFileContent(mConfig.config)), mId(getDomainName(mDom.get())), + mDetachOnExit(false), mLifecycleCallbackId(-1), mRebootCallbackId(-1), mNextIdForListener(0) @@ -106,6 +107,8 @@ ContainerAdmin::ContainerAdmin(ContainerConfig& config) ContainerAdmin::~ContainerAdmin() { + LOGD(mId << ": Destroying ContainerAdmin object..."); + // Deregister callbacks if (mLifecycleCallbackId >= 0) { virConnectDomainEventDeregisterAny(virDomainGetConnect(mDom.get()), @@ -117,11 +120,12 @@ ContainerAdmin::~ContainerAdmin() } // Try to forcefully stop - LOGD(mId << ": Destroying ContainerAdmin object..."); - try { - destroy(); - } catch (ServerException&) { - LOGE(mId << ": Failed to destroy the container"); + if (!mDetachOnExit) { + try { + destroy(); + } catch (ServerException&) { + LOGE(mId << ": Failed to destroy the container"); + } } LOGD(mId << ": ContainerAdmin object destroyed"); @@ -144,10 +148,10 @@ void ContainerAdmin::start() return; } - // Autodestroyed when connection pointer released - // Any managed save file for this domain is discarded, - // and the domain boots from scratch - u_int flags = VIR_DOMAIN_START_AUTODESTROY; + // In order to update daemon without shutting down the containers + // autodestroy option must NOT be set. It's best to create domain + // without any flags. + u_int flags = VIR_DOMAIN_NONE; if (virDomainCreateWithFlags(mDom.get(), flags) < 0) { LOGE(mId << ": Failed to start the container\n" @@ -362,6 +366,10 @@ void ContainerAdmin::setSchedulerParams(std::uint64_t cpuShares, std::uint64_t v } } +void ContainerAdmin::setDetachOnExit() +{ + mDetachOnExit = true; +} std::int64_t ContainerAdmin::getSchedulerQuota() { diff --git a/server/container-admin.hpp b/server/container-admin.hpp index add8f9a..ed1e00e 100644 --- a/server/container-admin.hpp +++ b/server/container-admin.hpp @@ -134,6 +134,11 @@ public: void setSchedulerLevel(SchedulerLevel sched); /** + * Set whether container should be detached on exit. + */ + void setDetachOnExit(); + + /** * @return Scheduler CFS quota, * TODO: this function is only for UNIT TESTS */ @@ -160,6 +165,7 @@ private: ContainerConfig& mConfig; libvirt::LibvirtDomain mDom; const std::string mId; + bool mDetachOnExit; int getState(); // get the libvirt's domain state void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota); diff --git a/server/container-connection-transport.cpp b/server/container-connection-transport.cpp index 7f4fb5e..3c14a67 100644 --- a/server/container-connection-transport.cpp +++ b/server/container-connection-transport.cpp @@ -43,7 +43,7 @@ const unsigned int TRANSPORT_READY_TIMEOUT = 2 * 60 * 1000; ContainerConnectionTransport::ContainerConnectionTransport(const std::string& runMountPoint) - : mRunMountPoint(runMountPoint) + : mRunMountPoint(runMountPoint), mDetachOnExit(false) { if (runMountPoint.empty()) { return; @@ -53,12 +53,20 @@ ContainerConnectionTransport::ContainerConnectionTransport(const std::string& ru throw ContainerConnectionException("Could not create: " + runMountPoint); } - // try to umount if already mounted - utils::umount(runMountPoint); + bool isMount = false; + if (!utils::isMountPoint(runMountPoint, isMount)) { + LOGE("Failed to check if " << runMountPoint << " is a mount point."); + throw ContainerConnectionException("Could not check if " + runMountPoint + + " is a mount point."); + } + + if (!isMount) { + LOGD(runMountPoint << " not mounted - mounting."); - if (!utils::mountTmpfs(runMountPoint)) { - LOGE("Initialization failed: could not mount " << runMountPoint); - throw ContainerConnectionException("Could not mount: " + runMountPoint); + if (!utils::mountTmpfs(runMountPoint)) { + LOGE("Initialization failed: could not mount " << runMountPoint); + throw ContainerConnectionException("Could not mount: " + runMountPoint); + } } // if there is no systemd in the container this dir won't be created automatically @@ -73,9 +81,11 @@ ContainerConnectionTransport::ContainerConnectionTransport(const std::string& ru ContainerConnectionTransport::~ContainerConnectionTransport() { - if (!mRunMountPoint.empty()) { - if (!utils::umount(mRunMountPoint)) { - LOGE("Deinitialization failed: could not umount " << mRunMountPoint); + if (!mDetachOnExit) { + if (!mRunMountPoint.empty()) { + if (!utils::umount(mRunMountPoint)) { + LOGE("Deinitialization failed: could not umount " << mRunMountPoint); + } } } } @@ -96,5 +106,9 @@ std::string ContainerConnectionTransport::acquireAddress() return "unix:path=" + dbusPath; } +void ContainerConnectionTransport::setDetachOnExit() +{ + mDetachOnExit = true; +} } // namespace security_containers diff --git a/server/container-connection-transport.hpp b/server/container-connection-transport.hpp index 989ba96..0be1035 100644 --- a/server/container-connection-transport.hpp +++ b/server/container-connection-transport.hpp @@ -46,8 +46,14 @@ public: */ std::string acquireAddress(); + /** + * Set whether object should detach from transport filesystem on exit + */ + void setDetachOnExit(); + private: std::string mRunMountPoint; + bool mDetachOnExit; }; diff --git a/server/container.cpp b/server/container.cpp index 4717429..a4ad5f1 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -103,6 +103,12 @@ void Container::goBackground() mAdmin->setSchedulerLevel(SchedulerLevel::BACKGROUND); } +void Container::setDetachOnExit() +{ + mAdmin->setDetachOnExit(); + mConnectionTransport->setDetachOnExit(); +} + bool Container::isRunning() { return mAdmin->isRunning(); diff --git a/server/container.hpp b/server/container.hpp index 5607715..26a94c5 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -79,6 +79,14 @@ public: void goBackground(); /** + * Set if container should be detached on exit. + * + * This sends detach flag to ContainerAdmin object and disables unmounting tmpfs + * in ContainerConnectionTransport. + */ + void setDetachOnExit(); + + /** * @return Is the container running? */ bool isRunning(); diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 288bdef..0aaebc7 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -36,7 +36,7 @@ namespace security_containers { -ContainersManager::ContainersManager(const std::string& managerConfigPath) +ContainersManager::ContainersManager(const std::string& managerConfigPath): mDetachOnExit(false) { LOGD("Instantiating ContainersManager object..."); mConfig.parseFile(managerConfigPath); @@ -64,11 +64,15 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath) ContainersManager::~ContainersManager() { LOGD("Destroying ContainersManager object..."); - try { - stopAll(); - } catch (ServerException&) { - LOGE("Failed to stop all of the containers"); + + if (!mDetachOnExit) { + try { + stopAll(); + } catch (ServerException&) { + LOGE("Failed to stop all of the containers"); + } } + LOGD("ContainersManager object destroyed"); } @@ -139,4 +143,13 @@ std::string ContainersManager::getRunningForegroundContainerId() } +void ContainersManager::setContainersDetachOnExit() +{ + mDetachOnExit = true; + + for (auto& container : mContainers) { + container.second->setDetachOnExit(); + } +} + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index e3a428c..920d5fd 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -66,10 +66,16 @@ public: */ std::string getRunningForegroundContainerId(); + /** + * Set whether ContainersManager should detach containers on exit + */ + void setContainersDetachOnExit(); + private: ContainersManagerConfig mConfig; typedef std::unordered_map> ContainerMap; ContainerMap mContainers; // map of containers, id is the key + bool mDetachOnExit; }; diff --git a/server/main.cpp b/server/main.cpp index d911071..395d936 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -114,6 +114,7 @@ int main(int argc, char* argv[]) try { Server server(configPath); server.run(); + server.reloadIfRequired(argv); } catch (std::exception& e) { LOGE("Unexpected: " << utils::getTypeName(e) << ": " << e.what()); diff --git a/server/server.cpp b/server/server.cpp index 01b0ab3..82d0a6d 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -30,7 +30,13 @@ #include "utils/glib-loop.hpp" #include +#include #include +#include +#include +#include + +extern char** environ; namespace security_containers { @@ -47,18 +53,29 @@ Server::~Server() namespace { -utils::Latch signalLatch; + +std::atomic_bool gUpdateTriggered(false); +utils::Latch gSignalLatch; + void signalHandler(const int sig) { LOGI("Got signal " << sig); - signalLatch.set(); -} + + if (sig == SIGUSR1) { + LOGD("Received SIGUSR1 - triggering update."); + gUpdateTriggered = true; + } + + gSignalLatch.set(); } +} // namespace + void Server::run() { signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); + signal(SIGUSR1, signalHandler); LOGI("Starting daemon..."); { @@ -68,7 +85,12 @@ void Server::run() manager.startAll(); LOGI("Daemon started"); - signalLatch.wait(); + gSignalLatch.wait(); + + // Detach containers if we triggered an update + if (gUpdateTriggered) { + manager.setContainersDetachOnExit(); + } LOGI("Stopping daemon..."); // manager.stopAll() will be called in destructor @@ -76,10 +98,19 @@ void Server::run() LOGI("Daemon stopped"); } +void Server::reloadIfRequired(char* argv[]) +{ + if (gUpdateTriggered) { + execve(argv[0], argv, environ); + + LOGE("Failed to reload " << argv[0] << ": " << strerror(errno)); + } +} + void Server::terminate() { LOGI("Terminating server"); - signalLatch.set(); + gSignalLatch.set(); } } // namespace security_containers diff --git a/server/server.hpp b/server/server.hpp index 59a1a35..abb8775 100644 --- a/server/server.hpp +++ b/server/server.hpp @@ -38,11 +38,16 @@ public: virtual ~Server(); /** - * Starts all the containers and blocks until SIGINT or SIGTERM + * Starts all the containers and blocks until SIGINT, SIGTERM or SIGUSR1 */ void run(); /** + * Reload the server by launching execve on itself if SIGUSR1 was sent to server. + */ + void reloadIfRequired(char* argv[]); + + /** * Terminates the server. * Equivalent of sending SIGINT or SIGTERM signal */ -- 2.7.4 From 8a7990d12c58f0680025cbb5eaf62343ad9baedd Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Thu, 15 May 2014 13:24:26 +0200 Subject: [PATCH 04/16] Mount smackfs into containers [Bug/Feature] There were no possibilities to check SMACK labels being inside the container [Cause] Smackfs was not mounted [Solution] N/A [Verification] Build, install, check the result of command: ls -1Z # (inside container) Should output labels, not '?' Change-Id: I8aaf961b05e87725df85b6031efb60c45142b977 --- server/configs/libvirt-config/business.xml | 7 +++++++ server/configs/libvirt-config/private.xml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/server/configs/libvirt-config/business.xml b/server/configs/libvirt-config/business.xml index f2317a8..8f044c0 100644 --- a/server/configs/libvirt-config/business.xml +++ b/server/configs/libvirt-config/business.xml @@ -109,5 +109,12 @@ + + + + + + diff --git a/server/configs/libvirt-config/private.xml b/server/configs/libvirt-config/private.xml index 7df0db4..26cf1f6 100644 --- a/server/configs/libvirt-config/private.xml +++ b/server/configs/libvirt-config/private.xml @@ -109,5 +109,12 @@ + + + + + + -- 2.7.4 From 76585ab1424d20a3bc9f856bdcb73d71d28b90f6 Mon Sep 17 00:00:00 2001 From: Michal Witanowski Date: Tue, 20 May 2014 10:09:14 +0200 Subject: [PATCH 05/16] Fix building without spec [Cause] Undefined macro. [Solution] SYSTEMD_UNIT_DIR defined in CMakeLists.txt. [Verification] Build with CMake. Change-Id: I42ee402003af07b51d3cf07bc5dadf7a5dc442af Signed-off-by: Michal Witanowski --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 964ba66..88a1eaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,10 @@ IF(NOT DEFINED SHARE_INSTALL_PREFIX) SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_FULL_DATAROOTDIR}") ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) +IF(NOT DEFINED SYSTEMD_UNIT_DIR) + SET(SYSTEMD_UNIT_DIR "${LIB_INSTALL_DIR}/systemd/system") +ENDIF(NOT DEFINED SYSTEMD_UNIT_DIR) + SET(SC_CONFIG_INSTALL_DIR ${SYSCONF_INSTALL_DIR}/security-containers) SET(SC_DATA_INSTALL_DIR ${SHARE_INSTALL_PREFIX}/security-containers) -- 2.7.4 From 9c72977e5629abc2326f2debd59b158112c668b6 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Mon, 19 May 2014 11:51:31 +0200 Subject: [PATCH 06/16] Mount containers /run folder with proper smack labels [Bug/Feature] Containers can't boot with SMACK. [Cause] /run is badly mounted from host [Solution] Add proper mount options. [Verification] Build, install, run server and ensure container is booting to the login prompt. You can also check if 'ls -laZ /run' prints 'System::Run' (assuming /sys/fs/smackfs is mounted). Verify also if /run is being mounted with no-smack kernel. Change-Id: Ife40353d9ac45c923a2e9ce4e48f44b4ca203cf4 --- common/utils/fs.cpp | 19 ++++++++++++++++--- common/utils/fs.hpp | 4 ++-- server/container-connection-transport.cpp | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index aac496f..3584496 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -99,15 +99,28 @@ bool createDirectories(const std::string& path, mode_t mode) return createDirectory(path, mode); } -bool mountTmpfs(const std::string& path) +namespace { +// NOTE: Should be the same as in systemd/src/core/mount-setup.c +const std::string RUN_MOUNT_POINT_OPTIONS = "mode=755,smackfstransmute=System::Run"; +const std::string RUN_MOUNT_POINT_OPTIONS_NO_SMACK = "mode=755"; +const unsigned long RUN_MOUNT_POINT_FLAGS = MS_NOSUID | MS_NODEV | MS_STRICTATIME; + +bool mountTmpfs(const std::string& path, unsigned long flags, const std::string& options) { - if (::mount("tmpfs", path.c_str(), "tmpfs", MS_NOSUID | MS_NODEV, "mode=755") != 0) { - LOGD("Mount failed for '" << path << "': " << strerror(errno)); + if (::mount("tmpfs", path.c_str(), "tmpfs", flags, options.c_str()) != 0) { + LOGD("Mount failed for '" << path << "', options=" << options << ": " << strerror(errno)); return false; } return true; } +} // namespace + +bool mountRun(const std::string& path) { + return utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS) || + utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK); +} + bool umount(const std::string& path) { if (::umount(path.c_str()) != 0) { diff --git a/common/utils/fs.hpp b/common/utils/fs.hpp index 95ce200..4dc601b 100644 --- a/common/utils/fs.hpp +++ b/common/utils/fs.hpp @@ -58,9 +58,9 @@ bool createDirectory(const std::string& path, mode_t mode); bool createDirectories(const std::string& path, mode_t mode); /** - * Mounts a tmpfs on given a path + * Mounts run as a tmpfs on a given path */ -bool mountTmpfs(const std::string& path); +bool mountRun(const std::string& path); /** * Umounts a filesystem diff --git a/server/container-connection-transport.cpp b/server/container-connection-transport.cpp index 3c14a67..d1704c5 100644 --- a/server/container-connection-transport.cpp +++ b/server/container-connection-transport.cpp @@ -63,7 +63,7 @@ ContainerConnectionTransport::ContainerConnectionTransport(const std::string& ru if (!isMount) { LOGD(runMountPoint << " not mounted - mounting."); - if (!utils::mountTmpfs(runMountPoint)) { + if (!utils::mountRun(runMountPoint)) { LOGE("Initialization failed: could not mount " << runMountPoint); throw ContainerConnectionException("Could not mount: " + runMountPoint); } -- 2.7.4 From 3b4ce59f186681296bce9dc2543b3a57d5f35646 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Tue, 20 May 2014 09:15:57 +0200 Subject: [PATCH 07/16] Handle the container restart from within gracefully with DBUS reconnection [Bug/Feature] You can now restart the container from within. [Cause] Restarting was stopped by the reconnection routine. [Solution] Reconnect tries few times with greater timeout before giving up. This gives the time for the container to restart. [Verification] Built, installed, run tests and the daemon. Change-Id: I0e4f1c248af9f0d2faf81662876b971c2b35ed02 Signed-off-by: Lukasz Pawelczyk --- server/container.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/server/container.cpp b/server/container.cpp index a4ad5f1..6ce6f24 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -34,6 +34,14 @@ namespace security_containers { +namespace { + +// TODO: move constants to the config file when default values are implemented there +const int RECONNECT_RETRIES = 15; +const int RECONNECT_DELAY = 1 * 1000; + +} // namespace + Container::Container(const std::string& containerConfigPath) { mConfig.parseFile(containerConfigPath); @@ -136,26 +144,30 @@ void Container::onNameLostCallback() void Container::reconnectHandler() { - std::string address; - mConnection.reset(); - try { - address = mConnectionTransport->acquireAddress(); - } catch (SecurityContainersException&) { - LOGE(getId() << "The socket does not exist anymore, something went terribly wrong, stopping the container"); - stop(); - return; + for (int i = 0; i < RECONNECT_RETRIES; ++i) { + // This sleeps even before the first try to give DBUS some time to come back up + std::this_thread::sleep_for(std::chrono::milliseconds(RECONNECT_DELAY)); + + if (isStopped()) { + LOGI(getId() << ": Has stopped, nothing to reconnect to, bailing out"); + return; + } + + try { + LOGT(getId() << ": Reconnect try " << i+1); + mConnection.reset(new ContainerConnection(mConnectionTransport->acquireAddress(), + std::bind(&Container::onNameLostCallback, this))); + LOGI(getId() << ": Reconnected"); + return; + } catch (SecurityContainersException&) { + LOGT(getId() << ": Reconnect try " << i+1 << " has been unsuccessful"); + } } - try { - mConnection.reset(new ContainerConnection(address, std::bind(&Container::onNameLostCallback, this))); - LOGI(getId() << ": Reconnected"); - } catch (SecurityContainersException&) { - LOGE(getId() << ": Reconnecting to the DBUS has failed, stopping the container"); - stop(); - return; - } + LOGE(getId() << ": Reconnecting to the DBUS has failed, stopping the container"); + stop(); } -- 2.7.4 From 0d0cca04f590d8c3a30154d6a52a0aec4bb07871 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Wed, 28 May 2014 17:14:53 +0200 Subject: [PATCH 08/16] Journal logger backend fixes [Bug/Feature] Some journal fields are incorrectly generated [Cause] N/A [Solution] - make PRIORITY values compatible with syslog - repair CODE_* fields by proper use of macro SD_JOURNAL_SUPPRESS_LOCATION [Verification] Build, install, run server, check the result of: journalctl -o json-pretty _COMM=security-contai Change-Id: I8904649ba1e40152346ba986c58f9dcb788bc94d --- common/log/backend-journal.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/common/log/backend-journal.cpp b/common/log/backend-journal.cpp index 032ab9b..7f43419 100644 --- a/common/log/backend-journal.cpp +++ b/common/log/backend-journal.cpp @@ -23,27 +23,46 @@ */ #include "log/backend-journal.hpp" -#include "log/formatter.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) { -#define SD_JOURNAL_SUPPRESS_LOCATION - sd_journal_send("PRIORITY=%s", toString(logLevel).c_str(), + 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); -#undef SD_JOURNAL_SUPPRESS_LOCATION } } // namespace log -- 2.7.4 From ff58c45a03bf2ed110821f8eba907a4a918dc06a Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Thu, 29 May 2014 10:42:20 +0200 Subject: [PATCH 09/16] Reorganize tests in security-containers [Feature] Reorganization of tests in security-containers [Cause] Integration tests will be added to security-containers. In order to keep repo clean all tests should be gathered in a "tests" directory and there divided into test categories. [Solution] Created "tests" directory and moved "unit_tests" to "tests" dir. Modified CMakeLists to make project buildable. Changed RPM name from ...-unit-tests to ...-tests [Verification] Build, install, run tests. All tests should work as they did before this commit. Change-Id: I6d6e89f913fa5e7eece8a8502472ac499bc71117 Signed-off-by: Lukasz Kostyra --- CMakeLists.txt | 7 ++++--- ...t => security-containers-server-tests.manifest} | 0 packaging/security-containers.spec | 12 ++++++------ tests/CMakeLists.txt | 22 ++++++++++++++++++++++ {unit_tests => tests}/scripts/CMakeLists.txt | 0 {unit_tests => tests}/scripts/sc_all_tests.py | 0 {unit_tests => tests}/scripts/sc_launch_test.py | 0 {unit_tests => tests}/scripts/sc_test_parser.py | 0 {unit_tests => tests/unit_tests}/CMakeLists.txt | 1 - .../unit_tests}/config/ut-configuration.cpp | 0 .../unit_tests}/dbus/configs/CMakeLists.txt | 0 .../dbus/configs/ut-connection/ut-dbus.conf | 0 .../unit_tests}/dbus/test-client.cpp | 0 .../unit_tests}/dbus/test-client.hpp | 0 .../unit_tests}/dbus/test-common.hpp | 0 .../unit_tests}/dbus/test-server.cpp | 0 .../unit_tests}/dbus/test-server.hpp | 0 .../unit_tests}/dbus/ut-connection.cpp | 0 .../unit_tests}/libvirt/connection.cpp | 0 .../unit_tests}/libvirt/domain.cpp | 0 {unit_tests => tests/unit_tests}/log/ut-logger.cpp | 0 .../unit_tests}/server/configs/CMakeLists.txt | 0 .../ut-container-admin/containers/buggy.conf.in | 0 .../ut-container-admin/containers/missing.conf | 0 .../containers/test-no-shutdown.conf.in | 0 .../ut-container-admin/containers/test.conf.in | 0 .../ut-container-admin/libvirt-config/buggy.xml | 0 .../libvirt-config/test-no-shutdown.xml | 0 .../ut-container-admin/libvirt-config/test.xml | 0 .../configs/ut-container-connection/ut-dbus.conf | 0 .../configs/ut-container/containers/buggy.conf | 0 .../configs/ut-container/containers/test-dbus.conf | 0 .../configs/ut-container/containers/test.conf | 0 .../ut-container/libvirt-config/test-dbus.xml.in | 0 .../configs/ut-container/libvirt-config/test.xml | 0 .../server/configs/ut-container/ut-dbus.conf | 0 .../ut-containers-manager/buggy-daemon.conf | 0 .../buggy-foreground-daemon.conf | 0 .../ut-containers-manager/containers/console1.conf | 0 .../ut-containers-manager/containers/console2.conf | 0 .../ut-containers-manager/containers/console3.conf | 0 .../libvirt-config/console1.xml | 0 .../libvirt-config/console2.xml | 0 .../libvirt-config/console3.xml | 0 .../configs/ut-containers-manager/test-daemon.conf | 0 .../server/configs/ut-server/buggy-daemon.conf | 0 .../configs/ut-server/containers/container1.conf | 0 .../configs/ut-server/containers/container2.conf | 0 .../configs/ut-server/containers/container3.conf | 0 .../ut-server/libvirt-config/container1.xml | 0 .../ut-server/libvirt-config/container2.xml | 0 .../ut-server/libvirt-config/container3.xml | 0 .../server/configs/ut-server/test-daemon.conf | 0 .../unit_tests}/server/ut-container-admin.cpp | 0 .../unit_tests}/server/ut-container-connection.cpp | 0 .../unit_tests}/server/ut-container.cpp | 0 .../unit_tests}/server/ut-containers-manager.cpp | 0 .../unit_tests}/server/ut-server.cpp | 0 {unit_tests => tests/unit_tests}/ut.cpp | 0 {unit_tests => tests/unit_tests}/ut.hpp | 0 .../unit_tests}/utils/configs/CMakeLists.txt | 0 .../unit_tests}/utils/configs/ut-fs/file.txt | 0 .../unit_tests}/utils/scoped-daemon.cpp | 0 .../unit_tests}/utils/scoped-daemon.hpp | 0 .../unit_tests}/utils/ut-callback-guard.cpp | 0 {unit_tests => tests/unit_tests}/utils/ut-fs.cpp | 0 .../unit_tests}/utils/ut-glib-loop.cpp | 0 .../unit_tests}/utils/ut-paths.cpp | 0 68 files changed, 32 insertions(+), 10 deletions(-) rename packaging/{security-containers-server-unit-tests.manifest => security-containers-server-tests.manifest} (100%) create mode 100644 tests/CMakeLists.txt rename {unit_tests => tests}/scripts/CMakeLists.txt (100%) rename {unit_tests => tests}/scripts/sc_all_tests.py (100%) rename {unit_tests => tests}/scripts/sc_launch_test.py (100%) rename {unit_tests => tests}/scripts/sc_test_parser.py (100%) rename {unit_tests => tests/unit_tests}/CMakeLists.txt (98%) rename {unit_tests => tests/unit_tests}/config/ut-configuration.cpp (100%) rename {unit_tests => tests/unit_tests}/dbus/configs/CMakeLists.txt (100%) rename {unit_tests => tests/unit_tests}/dbus/configs/ut-connection/ut-dbus.conf (100%) rename {unit_tests => tests/unit_tests}/dbus/test-client.cpp (100%) rename {unit_tests => tests/unit_tests}/dbus/test-client.hpp (100%) rename {unit_tests => tests/unit_tests}/dbus/test-common.hpp (100%) rename {unit_tests => tests/unit_tests}/dbus/test-server.cpp (100%) rename {unit_tests => tests/unit_tests}/dbus/test-server.hpp (100%) rename {unit_tests => tests/unit_tests}/dbus/ut-connection.cpp (100%) rename {unit_tests => tests/unit_tests}/libvirt/connection.cpp (100%) rename {unit_tests => tests/unit_tests}/libvirt/domain.cpp (100%) rename {unit_tests => tests/unit_tests}/log/ut-logger.cpp (100%) rename {unit_tests => tests/unit_tests}/server/configs/CMakeLists.txt (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/containers/buggy.conf.in (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/containers/missing.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/containers/test.conf.in (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/libvirt-config/buggy.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-admin/libvirt-config/test.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container-connection/ut-dbus.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/containers/buggy.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/containers/test-dbus.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/containers/test.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/libvirt-config/test-dbus.xml.in (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/libvirt-config/test.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-container/ut-dbus.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/buggy-daemon.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/buggy-foreground-daemon.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/containers/console1.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/containers/console2.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/containers/console3.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/libvirt-config/console1.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/libvirt-config/console2.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/libvirt-config/console3.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-containers-manager/test-daemon.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/buggy-daemon.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/containers/container1.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/containers/container2.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/containers/container3.conf (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/libvirt-config/container1.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/libvirt-config/container2.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/libvirt-config/container3.xml (100%) rename {unit_tests => tests/unit_tests}/server/configs/ut-server/test-daemon.conf (100%) rename {unit_tests => tests/unit_tests}/server/ut-container-admin.cpp (100%) rename {unit_tests => tests/unit_tests}/server/ut-container-connection.cpp (100%) rename {unit_tests => tests/unit_tests}/server/ut-container.cpp (100%) rename {unit_tests => tests/unit_tests}/server/ut-containers-manager.cpp (100%) rename {unit_tests => tests/unit_tests}/server/ut-server.cpp (100%) rename {unit_tests => tests/unit_tests}/ut.cpp (100%) rename {unit_tests => tests/unit_tests}/ut.hpp (100%) rename {unit_tests => tests/unit_tests}/utils/configs/CMakeLists.txt (100%) rename {unit_tests => tests/unit_tests}/utils/configs/ut-fs/file.txt (100%) rename {unit_tests => tests/unit_tests}/utils/scoped-daemon.cpp (100%) rename {unit_tests => tests/unit_tests}/utils/scoped-daemon.hpp (100%) rename {unit_tests => tests/unit_tests}/utils/ut-callback-guard.cpp (100%) rename {unit_tests => tests/unit_tests}/utils/ut-fs.cpp (100%) rename {unit_tests => tests/unit_tests}/utils/ut-glib-loop.cpp (100%) rename {unit_tests => tests/unit_tests}/utils/ut-paths.cpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88a1eaf..8c987dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +#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. @@ -59,7 +59,8 @@ SET(COMMON_FOLDER ${PROJECT_SOURCE_DIR}/common) SET(CLIENT_FOLDER ${PROJECT_SOURCE_DIR}/client) SET(SERVER_FOLDER ${PROJECT_SOURCE_DIR}/server) SET(CONTAINER_DAEMON_FOLDER ${PROJECT_SOURCE_DIR}/container-daemon) -SET(UNIT_TESTS_FOLDER ${PROJECT_SOURCE_DIR}/unit_tests) +SET(TESTS_FOLDER ${PROJECT_SOURCE_DIR}/tests) +SET(UNIT_TESTS_FOLDER ${TESTS_FOLDER}/unit_tests) IF(NOT DEFINED SYSCONF_INSTALL_DIR) SET(SYSCONF_INSTALL_DIR "/etc") @@ -91,5 +92,5 @@ SET(SC_DATA_INSTALL_DIR ${SHARE_INSTALL_PREFIX}/security-containers) ADD_SUBDIRECTORY(${CLIENT_FOLDER}) ADD_SUBDIRECTORY(${SERVER_FOLDER}) ADD_SUBDIRECTORY(${CONTAINER_DAEMON_FOLDER}) -ADD_SUBDIRECTORY(${UNIT_TESTS_FOLDER}) +ADD_SUBDIRECTORY(${TESTS_FOLDER}) diff --git a/packaging/security-containers-server-unit-tests.manifest b/packaging/security-containers-server-tests.manifest similarity index 100% rename from packaging/security-containers-server-unit-tests.manifest rename to packaging/security-containers-server-tests.manifest diff --git a/packaging/security-containers.spec b/packaging/security-containers.spec index 23b7bb3..b6c7e78 100644 --- a/packaging/security-containers.spec +++ b/packaging/security-containers.spec @@ -136,8 +136,8 @@ Daemon running inside every container. ## Test Package ################################################################ -%package unit-tests -Summary: Security Containers Unit Tests +%package tests +Summary: Security Containers Tests Group: Development/Libraries Requires: security-containers = %{version}-%{release} Requires: security-containers-client = %{version}-%{release} @@ -145,11 +145,11 @@ Requires: python Requires: boost-test BuildRequires: boost-devel -%description unit-tests -Unit tests for both: server and client. +%description tests +Unit tests for both: server and client and integration tests. -%files unit-tests -%manifest packaging/security-containers-server-unit-tests.manifest +%files tests +%manifest packaging/security-containers-server-tests.manifest %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/security-containers-server-unit-tests %attr(755,root,root) %{script_dir}/sc_all_tests.py diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..54dd155 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,22 @@ +#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 Lukasz Kostyra (l.kostyra@samsung.com) +# + +ADD_SUBDIRECTORY(scripts) +ADD_SUBDIRECTORY(unit_tests) + diff --git a/unit_tests/scripts/CMakeLists.txt b/tests/scripts/CMakeLists.txt similarity index 100% rename from unit_tests/scripts/CMakeLists.txt rename to tests/scripts/CMakeLists.txt diff --git a/unit_tests/scripts/sc_all_tests.py b/tests/scripts/sc_all_tests.py similarity index 100% rename from unit_tests/scripts/sc_all_tests.py rename to tests/scripts/sc_all_tests.py diff --git a/unit_tests/scripts/sc_launch_test.py b/tests/scripts/sc_launch_test.py similarity index 100% rename from unit_tests/scripts/sc_launch_test.py rename to tests/scripts/sc_launch_test.py diff --git a/unit_tests/scripts/sc_test_parser.py b/tests/scripts/sc_test_parser.py similarity index 100% rename from unit_tests/scripts/sc_test_parser.py rename to tests/scripts/sc_test_parser.py diff --git a/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt similarity index 98% rename from unit_tests/CMakeLists.txt rename to tests/unit_tests/CMakeLists.txt index e865049..51d9fd1 100644 --- a/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -44,7 +44,6 @@ TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_ SET(SC_TEST_CONFIG_INSTALL_DIR ${SC_DATA_INSTALL_DIR}/tests) ADD_DEFINITIONS(-DSC_TEST_CONFIG_INSTALL_DIR="${SC_TEST_CONFIG_INSTALL_DIR}") -ADD_SUBDIRECTORY(scripts) ADD_SUBDIRECTORY(dbus/configs) ADD_SUBDIRECTORY(server/configs) ADD_SUBDIRECTORY(utils/configs) diff --git a/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp similarity index 100% rename from unit_tests/config/ut-configuration.cpp rename to tests/unit_tests/config/ut-configuration.cpp diff --git a/unit_tests/dbus/configs/CMakeLists.txt b/tests/unit_tests/dbus/configs/CMakeLists.txt similarity index 100% rename from unit_tests/dbus/configs/CMakeLists.txt rename to tests/unit_tests/dbus/configs/CMakeLists.txt diff --git a/unit_tests/dbus/configs/ut-connection/ut-dbus.conf b/tests/unit_tests/dbus/configs/ut-connection/ut-dbus.conf similarity index 100% rename from unit_tests/dbus/configs/ut-connection/ut-dbus.conf rename to tests/unit_tests/dbus/configs/ut-connection/ut-dbus.conf diff --git a/unit_tests/dbus/test-client.cpp b/tests/unit_tests/dbus/test-client.cpp similarity index 100% rename from unit_tests/dbus/test-client.cpp rename to tests/unit_tests/dbus/test-client.cpp diff --git a/unit_tests/dbus/test-client.hpp b/tests/unit_tests/dbus/test-client.hpp similarity index 100% rename from unit_tests/dbus/test-client.hpp rename to tests/unit_tests/dbus/test-client.hpp diff --git a/unit_tests/dbus/test-common.hpp b/tests/unit_tests/dbus/test-common.hpp similarity index 100% rename from unit_tests/dbus/test-common.hpp rename to tests/unit_tests/dbus/test-common.hpp diff --git a/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp similarity index 100% rename from unit_tests/dbus/test-server.cpp rename to tests/unit_tests/dbus/test-server.cpp diff --git a/unit_tests/dbus/test-server.hpp b/tests/unit_tests/dbus/test-server.hpp similarity index 100% rename from unit_tests/dbus/test-server.hpp rename to tests/unit_tests/dbus/test-server.hpp diff --git a/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp similarity index 100% rename from unit_tests/dbus/ut-connection.cpp rename to tests/unit_tests/dbus/ut-connection.cpp diff --git a/unit_tests/libvirt/connection.cpp b/tests/unit_tests/libvirt/connection.cpp similarity index 100% rename from unit_tests/libvirt/connection.cpp rename to tests/unit_tests/libvirt/connection.cpp diff --git a/unit_tests/libvirt/domain.cpp b/tests/unit_tests/libvirt/domain.cpp similarity index 100% rename from unit_tests/libvirt/domain.cpp rename to tests/unit_tests/libvirt/domain.cpp diff --git a/unit_tests/log/ut-logger.cpp b/tests/unit_tests/log/ut-logger.cpp similarity index 100% rename from unit_tests/log/ut-logger.cpp rename to tests/unit_tests/log/ut-logger.cpp diff --git a/unit_tests/server/configs/CMakeLists.txt b/tests/unit_tests/server/configs/CMakeLists.txt similarity index 100% rename from unit_tests/server/configs/CMakeLists.txt rename to tests/unit_tests/server/configs/CMakeLists.txt diff --git a/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in similarity index 100% rename from unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in rename to tests/unit_tests/server/configs/ut-container-admin/containers/buggy.conf.in diff --git a/unit_tests/server/configs/ut-container-admin/containers/missing.conf b/tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf similarity index 100% rename from unit_tests/server/configs/ut-container-admin/containers/missing.conf rename to tests/unit_tests/server/configs/ut-container-admin/containers/missing.conf diff --git a/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 similarity index 100% rename from unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in rename to tests/unit_tests/server/configs/ut-container-admin/containers/test-no-shutdown.conf.in diff --git a/unit_tests/server/configs/ut-container-admin/containers/test.conf.in b/tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in similarity index 100% rename from unit_tests/server/configs/ut-container-admin/containers/test.conf.in rename to tests/unit_tests/server/configs/ut-container-admin/containers/test.conf.in diff --git a/unit_tests/server/configs/ut-container-admin/libvirt-config/buggy.xml b/tests/unit_tests/server/configs/ut-container-admin/libvirt-config/buggy.xml similarity index 100% rename from unit_tests/server/configs/ut-container-admin/libvirt-config/buggy.xml rename to tests/unit_tests/server/configs/ut-container-admin/libvirt-config/buggy.xml diff --git a/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml b/tests/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml similarity index 100% rename from unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml rename to tests/unit_tests/server/configs/ut-container-admin/libvirt-config/test-no-shutdown.xml diff --git a/unit_tests/server/configs/ut-container-admin/libvirt-config/test.xml b/tests/unit_tests/server/configs/ut-container-admin/libvirt-config/test.xml similarity index 100% rename from unit_tests/server/configs/ut-container-admin/libvirt-config/test.xml rename to tests/unit_tests/server/configs/ut-container-admin/libvirt-config/test.xml diff --git a/unit_tests/server/configs/ut-container-connection/ut-dbus.conf b/tests/unit_tests/server/configs/ut-container-connection/ut-dbus.conf similarity index 100% rename from unit_tests/server/configs/ut-container-connection/ut-dbus.conf rename to tests/unit_tests/server/configs/ut-container-connection/ut-dbus.conf diff --git a/unit_tests/server/configs/ut-container/containers/buggy.conf b/tests/unit_tests/server/configs/ut-container/containers/buggy.conf similarity index 100% rename from unit_tests/server/configs/ut-container/containers/buggy.conf rename to tests/unit_tests/server/configs/ut-container/containers/buggy.conf diff --git a/unit_tests/server/configs/ut-container/containers/test-dbus.conf b/tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf similarity index 100% rename from unit_tests/server/configs/ut-container/containers/test-dbus.conf rename to tests/unit_tests/server/configs/ut-container/containers/test-dbus.conf diff --git a/unit_tests/server/configs/ut-container/containers/test.conf b/tests/unit_tests/server/configs/ut-container/containers/test.conf similarity index 100% rename from unit_tests/server/configs/ut-container/containers/test.conf rename to tests/unit_tests/server/configs/ut-container/containers/test.conf diff --git a/unit_tests/server/configs/ut-container/libvirt-config/test-dbus.xml.in b/tests/unit_tests/server/configs/ut-container/libvirt-config/test-dbus.xml.in similarity index 100% rename from unit_tests/server/configs/ut-container/libvirt-config/test-dbus.xml.in rename to tests/unit_tests/server/configs/ut-container/libvirt-config/test-dbus.xml.in diff --git a/unit_tests/server/configs/ut-container/libvirt-config/test.xml b/tests/unit_tests/server/configs/ut-container/libvirt-config/test.xml similarity index 100% rename from unit_tests/server/configs/ut-container/libvirt-config/test.xml rename to tests/unit_tests/server/configs/ut-container/libvirt-config/test.xml diff --git a/unit_tests/server/configs/ut-container/ut-dbus.conf b/tests/unit_tests/server/configs/ut-container/ut-dbus.conf similarity index 100% rename from unit_tests/server/configs/ut-container/ut-dbus.conf rename to tests/unit_tests/server/configs/ut-container/ut-dbus.conf diff --git a/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf rename to tests/unit_tests/server/configs/ut-containers-manager/buggy-daemon.conf diff --git a/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf rename to tests/unit_tests/server/configs/ut-containers-manager/buggy-foreground-daemon.conf diff --git a/unit_tests/server/configs/ut-containers-manager/containers/console1.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/containers/console1.conf rename to tests/unit_tests/server/configs/ut-containers-manager/containers/console1.conf diff --git a/unit_tests/server/configs/ut-containers-manager/containers/console2.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/containers/console2.conf rename to tests/unit_tests/server/configs/ut-containers-manager/containers/console2.conf diff --git a/unit_tests/server/configs/ut-containers-manager/containers/console3.conf b/tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/containers/console3.conf rename to tests/unit_tests/server/configs/ut-containers-manager/containers/console3.conf diff --git a/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1.xml b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1.xml similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/libvirt-config/console1.xml rename to tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console1.xml diff --git a/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2.xml b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2.xml similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/libvirt-config/console2.xml rename to tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console2.xml diff --git a/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3.xml b/tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3.xml similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/libvirt-config/console3.xml rename to tests/unit_tests/server/configs/ut-containers-manager/libvirt-config/console3.xml diff --git a/unit_tests/server/configs/ut-containers-manager/test-daemon.conf b/tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf similarity index 100% rename from unit_tests/server/configs/ut-containers-manager/test-daemon.conf rename to tests/unit_tests/server/configs/ut-containers-manager/test-daemon.conf diff --git a/unit_tests/server/configs/ut-server/buggy-daemon.conf b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf similarity index 100% rename from unit_tests/server/configs/ut-server/buggy-daemon.conf rename to tests/unit_tests/server/configs/ut-server/buggy-daemon.conf diff --git a/unit_tests/server/configs/ut-server/containers/container1.conf b/tests/unit_tests/server/configs/ut-server/containers/container1.conf similarity index 100% rename from unit_tests/server/configs/ut-server/containers/container1.conf rename to tests/unit_tests/server/configs/ut-server/containers/container1.conf diff --git a/unit_tests/server/configs/ut-server/containers/container2.conf b/tests/unit_tests/server/configs/ut-server/containers/container2.conf similarity index 100% rename from unit_tests/server/configs/ut-server/containers/container2.conf rename to tests/unit_tests/server/configs/ut-server/containers/container2.conf diff --git a/unit_tests/server/configs/ut-server/containers/container3.conf b/tests/unit_tests/server/configs/ut-server/containers/container3.conf similarity index 100% rename from unit_tests/server/configs/ut-server/containers/container3.conf rename to tests/unit_tests/server/configs/ut-server/containers/container3.conf diff --git a/unit_tests/server/configs/ut-server/libvirt-config/container1.xml b/tests/unit_tests/server/configs/ut-server/libvirt-config/container1.xml similarity index 100% rename from unit_tests/server/configs/ut-server/libvirt-config/container1.xml rename to tests/unit_tests/server/configs/ut-server/libvirt-config/container1.xml diff --git a/unit_tests/server/configs/ut-server/libvirt-config/container2.xml b/tests/unit_tests/server/configs/ut-server/libvirt-config/container2.xml similarity index 100% rename from unit_tests/server/configs/ut-server/libvirt-config/container2.xml rename to tests/unit_tests/server/configs/ut-server/libvirt-config/container2.xml diff --git a/unit_tests/server/configs/ut-server/libvirt-config/container3.xml b/tests/unit_tests/server/configs/ut-server/libvirt-config/container3.xml similarity index 100% rename from unit_tests/server/configs/ut-server/libvirt-config/container3.xml rename to tests/unit_tests/server/configs/ut-server/libvirt-config/container3.xml diff --git a/unit_tests/server/configs/ut-server/test-daemon.conf b/tests/unit_tests/server/configs/ut-server/test-daemon.conf similarity index 100% rename from unit_tests/server/configs/ut-server/test-daemon.conf rename to tests/unit_tests/server/configs/ut-server/test-daemon.conf diff --git a/unit_tests/server/ut-container-admin.cpp b/tests/unit_tests/server/ut-container-admin.cpp similarity index 100% rename from unit_tests/server/ut-container-admin.cpp rename to tests/unit_tests/server/ut-container-admin.cpp diff --git a/unit_tests/server/ut-container-connection.cpp b/tests/unit_tests/server/ut-container-connection.cpp similarity index 100% rename from unit_tests/server/ut-container-connection.cpp rename to tests/unit_tests/server/ut-container-connection.cpp diff --git a/unit_tests/server/ut-container.cpp b/tests/unit_tests/server/ut-container.cpp similarity index 100% rename from unit_tests/server/ut-container.cpp rename to tests/unit_tests/server/ut-container.cpp diff --git a/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp similarity index 100% rename from unit_tests/server/ut-containers-manager.cpp rename to tests/unit_tests/server/ut-containers-manager.cpp diff --git a/unit_tests/server/ut-server.cpp b/tests/unit_tests/server/ut-server.cpp similarity index 100% rename from unit_tests/server/ut-server.cpp rename to tests/unit_tests/server/ut-server.cpp diff --git a/unit_tests/ut.cpp b/tests/unit_tests/ut.cpp similarity index 100% rename from unit_tests/ut.cpp rename to tests/unit_tests/ut.cpp diff --git a/unit_tests/ut.hpp b/tests/unit_tests/ut.hpp similarity index 100% rename from unit_tests/ut.hpp rename to tests/unit_tests/ut.hpp diff --git a/unit_tests/utils/configs/CMakeLists.txt b/tests/unit_tests/utils/configs/CMakeLists.txt similarity index 100% rename from unit_tests/utils/configs/CMakeLists.txt rename to tests/unit_tests/utils/configs/CMakeLists.txt diff --git a/unit_tests/utils/configs/ut-fs/file.txt b/tests/unit_tests/utils/configs/ut-fs/file.txt similarity index 100% rename from unit_tests/utils/configs/ut-fs/file.txt rename to tests/unit_tests/utils/configs/ut-fs/file.txt diff --git a/unit_tests/utils/scoped-daemon.cpp b/tests/unit_tests/utils/scoped-daemon.cpp similarity index 100% rename from unit_tests/utils/scoped-daemon.cpp rename to tests/unit_tests/utils/scoped-daemon.cpp diff --git a/unit_tests/utils/scoped-daemon.hpp b/tests/unit_tests/utils/scoped-daemon.hpp similarity index 100% rename from unit_tests/utils/scoped-daemon.hpp rename to tests/unit_tests/utils/scoped-daemon.hpp diff --git a/unit_tests/utils/ut-callback-guard.cpp b/tests/unit_tests/utils/ut-callback-guard.cpp similarity index 100% rename from unit_tests/utils/ut-callback-guard.cpp rename to tests/unit_tests/utils/ut-callback-guard.cpp diff --git a/unit_tests/utils/ut-fs.cpp b/tests/unit_tests/utils/ut-fs.cpp similarity index 100% rename from unit_tests/utils/ut-fs.cpp rename to tests/unit_tests/utils/ut-fs.cpp diff --git a/unit_tests/utils/ut-glib-loop.cpp b/tests/unit_tests/utils/ut-glib-loop.cpp similarity index 100% rename from unit_tests/utils/ut-glib-loop.cpp rename to tests/unit_tests/utils/ut-glib-loop.cpp diff --git a/unit_tests/utils/ut-paths.cpp b/tests/unit_tests/utils/ut-paths.cpp similarity index 100% rename from unit_tests/utils/ut-paths.cpp rename to tests/unit_tests/utils/ut-paths.cpp -- 2.7.4 From bd98e86a37b574acfb98f407bc007cdc018fb0a0 Mon Sep 17 00:00:00 2001 From: Piotr Bartosiewicz Date: Fri, 30 May 2014 11:14:15 +0200 Subject: [PATCH 10/16] Remove dead code in python test script [Bug/Feature] There is no need to colorize logs by script anymore since it is done by console log backend. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests, verify that logs are colored. Change-Id: Ie9b0acfa230d4b59184ca662256a51a4fec00e43 --- tests/scripts/sc_test_parser.py | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/tests/scripts/sc_test_parser.py b/tests/scripts/sc_test_parser.py index 0c87481..8d4b289 100644 --- a/tests/scripts/sc_test_parser.py +++ b/tests/scripts/sc_test_parser.py @@ -84,31 +84,10 @@ class Logger(object): -class Colorizer(object): - # Add new types of errors/tags for parser here - lineTypeDict = {'[ERROR]': RED + BOLD, - '[WARN ]': YELLOW + BOLD, - '[INFO ]': BLUE + BOLD, - '[DEBUG]': GREEN, - '[TRACE]': BLACK - } - - # Looks for lineTypeDict keywords in provided line and paints such line appropriately - def paintLine(self, line): - for key in self.lineTypeDict.iterkeys(): - if key in line: - return self.lineTypeDict[key] + line + ENDC - - return line - - - class Parser(object): _testResultBegin = "" _testResultEnd = "" - colorizer = Colorizer() - def __parseAndWriteLine(self, line): result = "" # Entire XML is kept in one line, if line begins with , extract it @@ -117,29 +96,22 @@ class Parser(object): line.find(self._testResultEnd) + len(self._testResultEnd)] line = line[0:line.find(self._testResultBegin)] + line[line.find(self._testResultEnd) + len(self._testResultEnd):] - sys.stdout.write(str(self.colorizer.paintLine(line))) + sys.stdout.write(line) sys.stdout.flush() return result def parseOutputFromProcess(self, p): - """Parses stdout from given subprocess p - colors printed lines and looks for test results. + """Parses stdout from given subprocess p. """ testResult = "" # Dump test results while True: outline = p.stdout.readline() testResult += self.__parseAndWriteLine(outline) - # If process returns a value, leave loop - if p.poll() != None: + # Break if process has ended and everything has been read + if not outline and p.poll() != None: break - # Sometimes the process might exit before we finish reading entire stdout - # Split ending of stdout in lines and finish reading it before ending the function - stdoutEnding = [s + '\n' for s in p.stdout.read().split('\n')] - for outline in stdoutEnding: - testResult += self.__parseAndWriteLine(outline) - return testResult - -- 2.7.4 From c36ce4dc72c6922382581a84dbc3eb60cb9e566c Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 28 May 2014 17:14:53 +0200 Subject: [PATCH 11/16] Moving to boost::filesystem [Bug/Feature] Some file system related functions are needed. [Cause] N/A [Solution] Deleted functions already implemented in boost:filesystem [Verification] Build, install, run tests Change-Id: Ic4e2c6fadecee739fde62c89bd441abd53d13390 Signed-off-by: Jan Olszak --- common/utils/fs.cpp | 45 +++---------------------------- common/utils/fs.hpp | 20 -------------- container-daemon/CMakeLists.txt | 2 +- server/CMakeLists.txt | 2 +- server/container-connection-transport.cpp | 19 ++++++++----- tests/unit_tests/CMakeLists.txt | 2 +- tests/unit_tests/dbus/ut-connection.cpp | 3 ++- 7 files changed, 22 insertions(+), 71 deletions(-) diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index 3584496..8b2956c 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -60,44 +60,6 @@ std::string readFileContent(const std::string& path) return content; } -bool removeFile(const std::string& path) -{ - if (::unlink(path.c_str()) != 0 && errno != ENOENT) { - LOGD("Could not remove file '" << path << "': " << strerror(errno)); - return false; - } - return true; -} - -bool isDirectory(const std::string& path) -{ - struct stat s; - return ::stat(path.c_str(), &s) == 0 && S_IFDIR == (s.st_mode & S_IFMT); -} - -bool createDirectory(const std::string& path, mode_t mode) -{ - if (::mkdir(path.c_str(), mode) == 0 && ::chmod(path.c_str(), mode) == 0) { - return true; - } - LOGD("Could not create directory '" << path << "': " << strerror(errno)); - return false; -} - -bool createDirectories(const std::string& path, mode_t mode) -{ - if (isDirectory(path)) { - return true; - } - std::string parent = dirName(path); - if (!parent.empty() && parent != path) { - if (!createDirectories(parent, mode)) { - return false; - } - } - - return createDirectory(path, mode); -} namespace { // NOTE: Should be the same as in systemd/src/core/mount-setup.c @@ -116,9 +78,10 @@ bool mountTmpfs(const std::string& path, unsigned long flags, const std::string& } // namespace -bool mountRun(const std::string& path) { - return utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS) || - utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK); +bool mountRun(const std::string& path) +{ + return utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS) + || utils::mountTmpfs(path, RUN_MOUNT_POINT_FLAGS, RUN_MOUNT_POINT_OPTIONS_NO_SMACK); } bool umount(const std::string& path) diff --git a/common/utils/fs.hpp b/common/utils/fs.hpp index 4dc601b..38b4fc6 100644 --- a/common/utils/fs.hpp +++ b/common/utils/fs.hpp @@ -38,26 +38,6 @@ namespace utils { std::string readFileContent(const std::string& path); /** - * Removes a file - */ -bool removeFile(const std::string& path); - -/** - * Checks if a directory exists - */ -bool isDirectory(const std::string& path); - -/** - * Creates a directory - */ -bool createDirectory(const std::string& path, mode_t mode); - -/** - * Creates a directory and its parents as needed - */ -bool createDirectories(const std::string& path, mode_t mode); - -/** * Mounts run as a tmpfs on a given path */ bool mountRun(const std::string& path); diff --git a/container-daemon/CMakeLists.txt b/container-daemon/CMakeLists.txt index 5cce2ad..c623798 100644 --- a/container-daemon/CMakeLists.txt +++ b/container-daemon/CMakeLists.txt @@ -29,7 +29,7 @@ ADD_EXECUTABLE(${CONTAINER_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## -FIND_PACKAGE (Boost COMPONENTS program_options REQUIRED) +FIND_PACKAGE (Boost COMPONENTS program_options) PKG_CHECK_MODULES(CONTAINER_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 020724c..42d9503 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -28,7 +28,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## -FIND_PACKAGE (Boost COMPONENTS program_options REQUIRED) +FIND_PACKAGE (Boost COMPONENTS program_options system filesystem) PKG_CHECK_MODULES(SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 libsystemd-journal) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) diff --git a/server/container-connection-transport.cpp b/server/container-connection-transport.cpp index d1704c5..71594f6 100644 --- a/server/container-connection-transport.cpp +++ b/server/container-connection-transport.cpp @@ -29,6 +29,8 @@ #include "utils/fs.hpp" #include "log/logger.hpp" +#include +#include namespace security_containers { @@ -48,9 +50,12 @@ ContainerConnectionTransport::ContainerConnectionTransport(const std::string& ru if (runMountPoint.empty()) { return; } - if (!utils::createDirectories(runMountPoint, 0755)) { - LOGE("Initialization failed: could not create " << runMountPoint); - throw ContainerConnectionException("Could not create: " + runMountPoint); + boost::system::error_code errorCode; + boost::filesystem::create_directories(runMountPoint, errorCode); + if (errorCode) { + LOGE("Initialization failed: could not create '" << runMountPoint << "' :" << errorCode); + throw ContainerConnectionException("Could not create: " + runMountPoint + + " :" + errorCode.message()); } bool isMount = false; @@ -72,9 +77,11 @@ ContainerConnectionTransport::ContainerConnectionTransport(const std::string& ru // if there is no systemd in the container this dir won't be created automatically // TODO: will require chown with USER namespace enabled std::string dbusDirectory = runMountPoint + "/dbus"; - if (!utils::createDirectories(dbusDirectory, 0755)) { - LOGE("Initialization failed: could not create " << dbusDirectory); - throw ContainerConnectionException("Could not create: " + dbusDirectory); + boost::filesystem::create_directories(dbusDirectory, errorCode); + if (errorCode) { + LOGE("Initialization failed: could not create '" << dbusDirectory << "' :" << errorCode); + throw ContainerConnectionException("Could not create: " + dbusDirectory + + " :" + errorCode.message()); } } diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 51d9fd1..816f058 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -32,7 +32,7 @@ ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRC ## Link libraries ############################################################## -FIND_PACKAGE (Boost COMPONENTS unit_test_framework REQUIRED) +FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem) PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 libsystemd-journal) INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER}) diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 483f901..6687f03 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -36,6 +36,7 @@ #include "utils/fs.hpp" #include "log/logger.hpp" +#include #include #include #include @@ -63,7 +64,7 @@ class ScopedDbusDaemon { public: ScopedDbusDaemon() { - utils::removeFile("/tmp/container_socket"); + boost::filesystem::remove("/tmp/container_socket"); mDaemon.start(DBUS_DAEMON_PROC, DBUS_DAEMON_ARGS); waitForFile(DBUS_SOCKET_FILE, DBUS_DAEMON_TIMEOUT); } -- 2.7.4 From 14b42dbf56d51db4540560a661fa707c93bb4a78 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Fri, 30 May 2014 18:14:51 +0200 Subject: [PATCH 12/16] Libvirt network wrapper [Bug/Feature] A wrapper for libvirt' network [Cause] N/A [Solution] N/A [Verification] Build, install, run tests. Change-Id: I0997f846132cc29035b144705ff4a4835a3dad01 --- common/libvirt/domain.cpp | 2 - common/libvirt/network.cpp | 71 ++++++++++++++++++++++++++++++ common/libvirt/network.hpp | 63 ++++++++++++++++++++++++++ tests/unit_tests/libvirt/domain.cpp | 2 +- tests/unit_tests/libvirt/network.cpp | 85 ++++++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 common/libvirt/network.cpp create mode 100644 common/libvirt/network.hpp create mode 100644 tests/unit_tests/libvirt/network.cpp diff --git a/common/libvirt/domain.cpp b/common/libvirt/domain.cpp index 1c6c52d..ae25a02 100644 --- a/common/libvirt/domain.cpp +++ b/common/libvirt/domain.cpp @@ -27,8 +27,6 @@ #include "libvirt/helpers.hpp" #include "libvirt/exception.hpp" -#include - namespace security_containers { namespace libvirt { diff --git a/common/libvirt/network.cpp b/common/libvirt/network.cpp new file mode 100644 index 0000000..fdb9126 --- /dev/null +++ b/common/libvirt/network.cpp @@ -0,0 +1,71 @@ +/* + * 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 Implementation of the class wrapping libvirt network + */ + +#include "log/logger.hpp" +#include "libvirt/network.hpp" +#include "libvirt/helpers.hpp" +#include "libvirt/exception.hpp" + + +namespace security_containers { +namespace libvirt { + + +LibvirtNetwork::LibvirtNetwork(const std::string& configXML) + : mCon(LIBVIRT_LXC_ADDRESS) +{ + mNet = virNetworkDefineXML(mCon.get(), configXML.c_str()); + + if (mNet == NULL) { + LOGE("Error while defining a network:\n" + << libvirtFormatError()); + throw LibvirtOperationException(); + } +} + +LibvirtNetwork::~LibvirtNetwork() +{ + if (virNetworkUndefine(mNet) < 0) { + LOGE("Error while undefining the network:\n" + << libvirtFormatError()); + } + + if (virNetworkFree(mNet) < 0) { + LOGE("Error while destroying the network object:\n" + << libvirtFormatError()); + } +} + +virNetworkPtr LibvirtNetwork::get() +{ + return mNet; +} + +LibvirtNetwork::operator bool() const +{ + return mNet != NULL; +} + +} // namespace libvirt +} // namespace security_containers diff --git a/common/libvirt/network.hpp b/common/libvirt/network.hpp new file mode 100644 index 0000000..5c5626e --- /dev/null +++ b/common/libvirt/network.hpp @@ -0,0 +1,63 @@ +/* + * 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 Declaration of the class wrapping libvirt network + */ + +#ifndef COMMON_LIBVIRT_NETWORK_HPP +#define COMMON_LIBVIRT_NETWORK_HPP + +#include "libvirt/connection.hpp" + +#include + + +namespace security_containers { +namespace libvirt { + + +class LibvirtNetwork { + +public: + LibvirtNetwork(const std::string& configXML); + ~LibvirtNetwork(); + + /** + * @return The libvirt network pointer + */ + virNetworkPtr get(); + + /** + * @return libvirt network pointer is not NULL + */ + operator bool() const; + +private: + LibvirtConnection mCon; + virNetworkPtr mNet = NULL; +}; + + +} // namespace libvirt +} // namespace security_containers + + +#endif // COMMON_LIBVIRT_NETWORK_HPP diff --git a/tests/unit_tests/libvirt/domain.cpp b/tests/unit_tests/libvirt/domain.cpp index b05fa5a..2ecbcc3 100644 --- a/tests/unit_tests/libvirt/domain.cpp +++ b/tests/unit_tests/libvirt/domain.cpp @@ -20,7 +20,7 @@ /** * @file * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com) - * @brief Unit tests of the ContainerAdmin class + * @brief Unit tests of the LibvirtDomain class */ #include "ut.hpp" diff --git a/tests/unit_tests/libvirt/network.cpp b/tests/unit_tests/libvirt/network.cpp new file mode 100644 index 0000000..7f862f7 --- /dev/null +++ b/tests/unit_tests/libvirt/network.cpp @@ -0,0 +1,85 @@ +/* + * 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 tests of the LibvirtNetwork class + */ + +#include "ut.hpp" + +#include "libvirt/network.hpp" +#include "libvirt/exception.hpp" + +#include + +BOOST_AUTO_TEST_SUITE(LibvirtNetworkSuite) + + +using namespace security_containers; +using namespace security_containers::libvirt; + + +namespace { + +const std::string CORRECT_CONFIG_XML = "" + " test" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +const std::string BUGGY_CONFIG_XML = "<>"; + +} // namespace + +BOOST_AUTO_TEST_CASE(ConstructorDestructorTest) +{ + std::unique_ptr netPtr; + BOOST_REQUIRE_NO_THROW(netPtr.reset(new LibvirtNetwork(CORRECT_CONFIG_XML))); + BOOST_REQUIRE_NO_THROW(netPtr.reset()); +} + +BOOST_AUTO_TEST_CASE(BuggyConfigTest) +{ + BOOST_REQUIRE_THROW(LibvirtNetwork net(BUGGY_CONFIG_XML), LibvirtOperationException); +} + +BOOST_AUTO_TEST_CASE(DefinitionTest) +{ + LibvirtNetwork net(CORRECT_CONFIG_XML); + BOOST_CHECK(net.get() != NULL); +} + +BOOST_AUTO_TEST_CASE(BoolTest) +{ + LibvirtNetwork net(CORRECT_CONFIG_XML); + BOOST_CHECK(net); +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From dce78fc5d1556b73c49cee3773f007eebd307653 Mon Sep 17 00:00:00 2001 From: Pawel Broda Date: Tue, 20 May 2014 10:36:57 +0200 Subject: [PATCH 13/16] Input monitor [Feature] Monitoring of events on input device files. [Cause] There is no possibility to use *home button* in native apps (there is no API for that). [Solution] *Input monitor* class is added. It allows to watch events on given device (not only *home button*). When a pattern given in .conf file is recognized, appropriate action is taken (i.e. callback). [Verification] Compiled, built and run. Conflicts: common/utils/fs.cpp common/utils/fs.hpp server/containers-manager.hpp Change-Id: I7bddd917e6da8d70c26c4188a640638669430619 Signed-off-by: Pawel Broda Signed-off-by: Jan Olszak --- common/config/configuration.hpp | 4 +- common/utils/fs.cpp | 24 ++ common/utils/fs.hpp | 11 + server/configs/daemon.conf | 7 +- server/containers-manager-config.hpp | 8 + server/containers-manager.cpp | 14 + server/containers-manager.hpp | 6 + server/exception.hpp | 8 + server/input-monitor-config.hpp | 62 ++++ server/input-monitor.cpp | 263 ++++++++++++++++ server/input-monitor.hpp | 70 +++++ .../ut-containers-manager/buggy-daemon.conf | 7 +- .../buggy-foreground-daemon.conf | 7 +- .../configs/ut-containers-manager/test-daemon.conf | 7 +- .../server/configs/ut-server/buggy-daemon.conf | 7 +- .../server/configs/ut-server/test-daemon.conf | 7 +- unit_tests/server/ut-input-monitor.cpp | 334 +++++++++++++++++++++ 17 files changed, 838 insertions(+), 8 deletions(-) create mode 100644 server/input-monitor-config.hpp create mode 100644 server/input-monitor.cpp create mode 100644 server/input-monitor.hpp create mode 100644 unit_tests/server/ut-input-monitor.cpp diff --git a/common/config/configuration.hpp b/common/config/configuration.hpp index 810721a..d6ebada 100644 --- a/common/config/configuration.hpp +++ b/common/config/configuration.hpp @@ -114,14 +114,14 @@ public: void parseFile(const std::string& path); /** - * Convert cofig object to string. + * Convert config object to string. * This method throws ConfigException when fails. * @return String in JSON format */ std::string toString() const; /** - * Write cofig object to a file (in JSON format). + * Write config object to a file (in JSON format). * This method throws ConfigException when fails. * @param path Target file path */ diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index 8b2956c..c8e0029 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -27,12 +27,14 @@ #include "utils/paths.hpp" #include "utils/exception.hpp" +#include #include #include #include #include #include #include +#include #include @@ -60,6 +62,28 @@ std::string readFileContent(const std::string& path) return content; } +bool isCharDevice(const std::string& path) +{ + struct stat s; + return ::stat(path.c_str(), &s) == 0 && S_IFCHR == (s.st_mode & S_IFMT); +} + +bool listDir(const std::string& path, std::vector& files) +{ + DIR *dirp = ::opendir(path.c_str()); + if(dirp == NULL) { + LOGE("Could not open directory" << path << "': " << strerror(errno)); + return false; + } + + struct dirent *entry; + while ((entry = ::readdir(dirp)) != NULL) { + files.push_back(entry->d_name); + } + + ::closedir(dirp); + return true; +} namespace { // NOTE: Should be the same as in systemd/src/core/mount-setup.c diff --git a/common/utils/fs.hpp b/common/utils/fs.hpp index 38b4fc6..c8f7efc 100644 --- a/common/utils/fs.hpp +++ b/common/utils/fs.hpp @@ -27,6 +27,7 @@ #include #include +#include namespace security_containers { @@ -38,6 +39,16 @@ namespace utils { std::string readFileContent(const std::string& path); /** + * Checks if a char device exists + */ +bool isCharDevice(const std::string& path); + +/** + * List all (including '.' and '..' entries) dir entries + */ +bool listDir(const std::string& path, std::vector& files); + +/** * Mounts run as a tmpfs on a given path */ bool mountRun(const std::string& path); diff --git a/server/configs/daemon.conf b/server/configs/daemon.conf index 84f871f..c68a9f3 100644 --- a/server/configs/daemon.conf +++ b/server/configs/daemon.conf @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/private.conf", "containers/business.conf" ], - "foregroundId" : "private" + "foregroundId" : "private", + "inputConfig" : {"enabled" : true, + "device" : "gpio-keys.4", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } diff --git a/server/containers-manager-config.hpp b/server/containers-manager-config.hpp index a8c3565..453b031 100644 --- a/server/containers-manager-config.hpp +++ b/server/containers-manager-config.hpp @@ -27,6 +27,7 @@ #define SERVER_CONTAINERS_MANAGER_CONFIG_HPP #include "config/configuration.hpp" +#include "input-monitor-config.hpp" #include #include @@ -38,6 +39,12 @@ namespace security_containers { const std::string CONTAINERS_MANAGER_CONFIG_PATH = "/etc/security-containers/config/daemon.conf"; struct ContainersManagerConfig : public config::ConfigurationBase { + + /** + * Parameters describing input device used to switch between containers + */ + InputConfig inputConfig; + /** * List of containers' configs that we manage. * File paths can be relative to the ContainerManager config file. @@ -52,6 +59,7 @@ struct ContainersManagerConfig : public config::ConfigurationBase { CONFIG_REGISTER { CONFIG_VALUE(containerConfigs) CONFIG_VALUE(foregroundId) + CONFIG_SUB_OBJECT(inputConfig) } }; diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 0aaebc7..20c1f98 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -58,6 +58,14 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet } LOGD("ContainersManager object instantiated"); + + if (mConfig.inputConfig.enabled) { + LOGI("Registering input monitor [" << mConfig.inputConfig.device.c_str() << "]"); + mSwitchingSequenceMonitor.reset( + new InputMonitor(mConfig.inputConfig, + std::bind(&ContainersManager::switchingSequenceMonitorNotify, + this))); + } } @@ -142,6 +150,12 @@ std::string ContainersManager::getRunningForegroundContainerId() return std::string(); } +void ContainersManager::switchingSequenceMonitorNotify() +{ + LOGI("switchingSequenceMonitorNotify() called"); + // TODO: implement +} + void ContainersManager::setContainersDetachOnExit() { diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 920d5fd..716f390 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -28,10 +28,12 @@ #include "container.hpp" #include "containers-manager-config.hpp" +#include "input-monitor.hpp" #include #include #include +#include namespace security_containers { @@ -73,9 +75,13 @@ public: private: ContainersManagerConfig mConfig; + // to hold InputMonitor pointer to monitor if container switching sequence is recognized + std::unique_ptr mSwitchingSequenceMonitor; typedef std::unordered_map> ContainerMap; ContainerMap mContainers; // map of containers, id is the key bool mDetachOnExit; + + void switchingSequenceMonitorNotify(); }; diff --git a/server/exception.hpp b/server/exception.hpp index 3b05bdb..3291f79 100644 --- a/server/exception.hpp +++ b/server/exception.hpp @@ -54,6 +54,14 @@ struct ContainerConnectionException: public ServerException { using ServerException::ServerException; }; +/** +* Exception during performing an operation by input monitor, +* e.g. create channel, register callback etc. +*/ +struct InputMonitorException: public ServerException { + using ServerException::ServerException; +}; + } diff --git a/server/input-monitor-config.hpp b/server/input-monitor-config.hpp new file mode 100644 index 0000000..99bac85 --- /dev/null +++ b/server/input-monitor-config.hpp @@ -0,0 +1,62 @@ +/* + * 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 Declaration of the struct for storing input monitor configuration + */ + + +#ifndef SERVER_INPUT_MONITOR_CONFIG_HPP +#define SERVER_INPUT_MONITOR_CONFIG_HPP + + +#include "config/configuration.hpp" + +#include + + +namespace security_containers { + +struct InputConfig : public config::ConfigurationBase { + + bool enabled; + + /** + * represents either a device name or an absolute device file path (must be a string starting + * with '/' character) + */ + std::string device; + int code; + int numberOfEvents; + int timeWindowMs; + + CONFIG_REGISTER { + CONFIG_VALUE(enabled) + CONFIG_VALUE(device) + CONFIG_VALUE(code) + CONFIG_VALUE(numberOfEvents) + CONFIG_VALUE(timeWindowMs) + } + +}; + +} // namespace security_containers + +#endif /* SERVER_INPUT_MONITOR_CONFIG_HPP */ diff --git a/server/input-monitor.cpp b/server/input-monitor.cpp new file mode 100644 index 0000000..ec8c300 --- /dev/null +++ b/server/input-monitor.cpp @@ -0,0 +1,263 @@ +/* + * 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 C++ wrapper for glib input monitor + */ + +#include "exception.hpp" +#include "input-monitor.hpp" +#include "input-monitor-config.hpp" + +#include "log/logger.hpp" +#include "utils/exception.hpp" +#include "utils/fs.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace security_containers { + +// TODO: extract device helper and monitoring utilities from InputMonitor to separate files + + +const std::string InputMonitor::DEVICE_DIR = "/dev/input/"; + + +std::string InputMonitor::findDeviceNode(const std::string& deviceName) +{ + std::vector files; + + try { + utils::listDir(DEVICE_DIR, files); + } catch (UtilsException&) { + throw InputMonitorException(); + } + + for (auto fileName: files) { + std::string fullDevicePath = DEVICE_DIR + fileName; + if (utils::isCharDevice(fullDevicePath)) { + char name[DEVICE_NAME_LENGTH]; + memset(name, 0, sizeof(name)); + int fd = open(fullDevicePath.c_str(), O_RDONLY); + if (fd < 0) { + LOGD("Failed to open'" << fullDevicePath << "'"); + continue; + } + + if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) { + LOGD("Failed to send ioctl with request about device name to '" + << fullDevicePath << "'"); + close(fd); + continue; + } + + close(fd); + + if (deviceName == name) { + LOGI("Device file for '" << deviceName << "' found under '" + << fullDevicePath << "'"); + return fullDevicePath; + } + } + } + + return std::string(); +} + +bool InputMonitor::detectExpectedEvent(const struct input_event& ie) +{ + // log events. Example log: + // Event detected [/dev/input/event4]: + // time: 946705528.918966 sec + // type, code, value: 1, 139, 1 + LOGT("Event detected [" << mConfig.device.c_str() << "]:\n" + << "\ttime: " << ie.time.tv_sec << "." << ie.time.tv_usec << " sec\n" + << "\ttype, code, value: " << ie.type << ", " << ie.code << ", " << ie.value); + + if (ie.type == EV_KEY && + ie.code == mConfig.code && + ie.value == KEY_PRESSED) { + for (int i = mConfig.numberOfEvents - 1; i > 0; --i) { + mEventTime[i].tv_sec = mEventTime[i - 1].tv_sec; + mEventTime[i].tv_usec = mEventTime[i - 1].tv_usec; + } + + mEventTime[0].tv_sec = ie.time.tv_sec; + mEventTime[0].tv_usec = ie.time.tv_usec; + + // a) check, if given event sequence happened within specified time window + // (this is necessary, because of multiplying in the next step) + // b) if yes, then compute the difference between the first and the last one + if (((mEventTime[0].tv_sec - mEventTime[mConfig.numberOfEvents - 1].tv_sec) < MAX_TIME_WINDOW_SEC) && + (mEventTime[0].tv_sec - mEventTime[mConfig.numberOfEvents - 1].tv_sec) * 1000000L + + mEventTime[0].tv_usec - mEventTime[mConfig.numberOfEvents - 1].tv_usec < mConfig.timeWindowMs * 1000L) { + + resetEventsTime(); + + return true; + } + } + + return false; +} + +void InputMonitor::readDevice(GIOChannel* gio) +{ + struct input_event ie; + gchar buff[sizeof(struct input_event)]; + gsize nBytesRequested = sizeof(struct input_event); + gsize nBytesRead = 0; + gsize nBytesReadTotal = 0; + GError *err = NULL; + + do { + GIOStatus readStatus = g_io_channel_read_chars(gio, + &buff[nBytesReadTotal], + nBytesRequested, + &nBytesRead, + &err); + + if (readStatus == G_IO_STATUS_ERROR || err != NULL) { + LOGE("Read from input monitor channel failed"); + return; + } + + nBytesRequested -= nBytesRead; + nBytesReadTotal += nBytesRead; + } while (nBytesRequested > 0); + + memcpy(&ie, buff, sizeof(struct input_event)); + + if (detectExpectedEvent(ie)) { + LOGI("Input monitor detected pattern."); + mNotifyCallback(); + } +} + +gboolean InputMonitor::readDeviceCallback(GIOChannel* gio, + GIOCondition /*condition*/, + gpointer data) +{ + InputMonitor& inputMonitor = *reinterpret_cast(data); + inputMonitor.readDevice(gio); + + return TRUE; +} + +InputMonitor::InputMonitor(const InputConfig& inputConfig, + const InputNotifyCallback& inputNotifyCallback) +{ + mConfig = inputConfig; + mNotifyCallback = inputNotifyCallback; + + resetEventsTime(); + + if (mConfig.numberOfEvents > MAX_NUMBER_OF_EVENTS) { + LOGE("Input monitor numberOfEvents > MAX_NUMBER_OF_EVENTS\n" + << "\twhere MAX_NUMBER_OF_EVENTS = " << MAX_NUMBER_OF_EVENTS); + throw InputMonitorException(); + } + + if (mConfig.timeWindowMs > MAX_TIME_WINDOW_SEC * 1000L) { + LOGE("Input monitor timeWindowMs > MAX_TIME_WINDOW_SEC * 1000L\n" + << "\twhere MAX_TIME_WINDOW_SEC = " << MAX_TIME_WINDOW_SEC); + throw InputMonitorException(); + } + + std::string devicePath; + if (mConfig.device[0] == '/') { // device file path is given + devicePath = mConfig.device; + } else { // device name is given - device file path is to be determined + LOGT("Determining, which device node is assigned to '" << mConfig.device << "'"); + devicePath = findDeviceNode(mConfig.device); + if (devicePath.empty()) { + LOGE("None of the files under '" << DEVICE_DIR << "' represents device named: " + << mConfig.device.c_str()); + throw InputMonitorException(); + } + } + + LOGT("Input monitor configuration: \n" + << "\tenabled: " << mConfig.enabled << "\n" + << "\tdevice: " << mConfig.device.c_str() << "\n" + << "\tpath: " << devicePath.c_str() << "\n" + << "\ttype: " << EV_KEY << "\n" + << "\tcode: " << mConfig.code << "\n" + << "\tvalue: " << KEY_PRESSED << "\n" + << "\tnumberOfEvents: " << mConfig.numberOfEvents << "\n" + << "\ttimeWindowMs: " << mConfig.timeWindowMs); + + GError *err = NULL; + + // creating channel using steps below, i.e.: + // 1) open() + // 2) g_io_channel_unix_new() + // was chosen, because glib API does not allow to open a file + // in a non-blocking mode. There is no argument to pass additional + // flags and we need such a mode for FIFOs in the tests. + int fd = open(devicePath.c_str(), O_RDONLY | O_NONBLOCK); + if (fd < 0) { + LOGE("Cannot create input monitor channel. Device file: " << devicePath.c_str() + << " doesn't exist" ); + throw InputMonitorException(); + } + + GIOChannel *mChannel = g_io_channel_unix_new(fd); + + // close the channel on final unref + g_io_channel_set_close_on_unref(mChannel, + TRUE); + + // read binary + g_io_channel_set_encoding(mChannel, + NULL, + &err); + + if (err != NULL) { + LOGE("Cannot set encoding for input monitor channel"); + throw InputMonitorException(); + } + + if (!g_io_add_watch(mChannel, G_IO_IN, readDeviceCallback, this)) { + LOGE("Cannot add watch on device input file"); + throw InputMonitorException(); + } +} + +void InputMonitor::resetEventsTime() +{ + memset(mEventTime, 0, sizeof(struct timeval) * MAX_NUMBER_OF_EVENTS); +} + +InputMonitor::~InputMonitor() +{ +} + +} // namespace security_containers diff --git a/server/input-monitor.hpp b/server/input-monitor.hpp new file mode 100644 index 0000000..692a554 --- /dev/null +++ b/server/input-monitor.hpp @@ -0,0 +1,70 @@ +/* + * 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 C++ wrapper for glib input monitor + */ + +#ifndef SERVER_INPUT_MONITOR_HPP +#define SERVER_INPUT_MONITOR_HPP + + +#include "input-monitor-config.hpp" + +#include +#include +#include +#include + + +namespace security_containers { + + +class InputMonitor { +public: + typedef std::function InputNotifyCallback; + InputMonitor(const InputConfig&, const InputNotifyCallback&); + ~InputMonitor(); + +private: + static const int MAX_NUMBER_OF_EVENTS = 5; + static const int MAX_TIME_WINDOW_SEC = 10; + static const int KEY_PRESSED = 1; + static const int DEVICE_NAME_LENGTH = 256; + static const std::string DEVICE_DIR; + struct timeval mEventTime[MAX_NUMBER_OF_EVENTS]; + GIOChannel *mChannel; + InputConfig mConfig; + + // External callback to be registered at InputMonitor instance + InputNotifyCallback mNotifyCallback; + + // Internal callback to be registered at glib g_io_add_watch() + static gboolean readDeviceCallback(GIOChannel *, GIOCondition, gpointer); + std::string findDeviceNode(const std::string&); + bool detectExpectedEvent(const struct input_event&); + void readDevice(GIOChannel *); + void resetEventsTime(); +}; + +} // namespace security_containers + + +#endif // SERVER_INPUT_MONITOR_HPP 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 6fe1813..ec42fdc 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 @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/console1.conf", "missing/file/path/missing.conf", "containers/console3.conf"], - "foregroundId" : "ut-containers-manager-console1" + "foregroundId" : "ut-containers-manager-console1", + "inputConfig" : {"enabled" : false, + "device" : "/dev/doesnotexist", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } 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 780e97e..0bb38b7 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 @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/console1.conf", "containers/console2.conf", "containers/console3.conf"], - "foregroundId" : "this_id_does_not_exist" + "foregroundId" : "this_id_does_not_exist", + "inputConfig" : {"enabled" : false, + "device" : "/dev/doesnotexist", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } 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 bd79b32..29ac710 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 @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/console1.conf", "containers/console2.conf", "containers/console3.conf"], - "foregroundId" : "ut-containers-manager-console1" + "foregroundId" : "ut-containers-manager-console1", + "inputConfig" : {"enabled" : false, + "device" : "/dev/doesnotexist", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } 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 6538dc9..0d27a85 100644 --- a/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/buggy-daemon.conf @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/container1.conf", "missing/file/path/missing.conf", "containers/container3.conf"], - "foregroundId" : "ut-server-container1" + "foregroundId" : "ut-server-container1", + "inputConfig" : {"enabled" : false, + "device" : "/dev/doesnotexist", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } 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 6777f7f..fc55c54 100644 --- a/tests/unit_tests/server/configs/ut-server/test-daemon.conf +++ b/tests/unit_tests/server/configs/ut-server/test-daemon.conf @@ -1,4 +1,9 @@ { "containerConfigs" : ["containers/container1.conf", "containers/container2.conf", "containers/container3.conf"], - "foregroundId" : "ut-server-container1" + "foregroundId" : "ut-server-container1", + "inputConfig" : {"enabled" : false, + "device" : "gpio-keys.4", + "code" : 139, + "numberOfEvents" : 2, + "timeWindowMs" : 500} } diff --git a/unit_tests/server/ut-input-monitor.cpp b/unit_tests/server/ut-input-monitor.cpp new file mode 100644 index 0000000..31b02ea --- /dev/null +++ b/unit_tests/server/ut-input-monitor.cpp @@ -0,0 +1,334 @@ +/* + * 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 Unit tests of the InputMonitor class + */ + +#include "ut.hpp" + +#include "input-monitor.hpp" +#include "input-monitor-config.hpp" +#include "exception.hpp" + +#include "utils/glib-loop.hpp" +#include "utils/latch.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +BOOST_AUTO_TEST_SUITE(InputMonitorSuite) + +using namespace security_containers; +using namespace security_containers::config; +using namespace security_containers::utils; + +namespace { + +const char* TEST_INPUT_DEVICE = "/tmp/testInputDevice"; + +const int EVENT_TYPE = 1; +const int EVENT_CODE = 139; +const int EVENT_BUTTON_RELEASED = 0; +const int EVENT_BUTTON_PRESSED = 1; + +const unsigned int ONE_EVENT = 1; +const unsigned int TEN_EVENTS = 10; + +const int SINGLE_EVENT_TIMEOUT = 10; + +std::atomic counter(0); + + +void callbackEmpty() +{ +} + +void callbackCounter() +{ + counter++; +} + +void resetCounter() +{ + counter = 0; +} + +unsigned int getCounter() +{ + return counter; +} + +/* + * A wrapper for write() which restarts after EINTR. + */ +ssize_t safeWrite(int fd, const void *buff, size_t len) +{ + size_t totalBytesWritten = 0; + + while (len > 0) { + ssize_t bytesWritten = write(fd, buff, len); + + if (bytesWritten < 0 && errno == EINTR) { + continue; + } + + if (bytesWritten < 0) { + return bytesWritten; + } + + if (bytesWritten == 0) { + return totalBytesWritten; + } + + buff = (const char *)buff + bytesWritten; + len -= bytesWritten; + totalBytesWritten += bytesWritten; + } + + return totalBytesWritten; +} + +class Fixture { +public: + InputConfig inputConfig; + utils::ScopedGlibLoop mLoop; + struct input_event ie[2]; + + Fixture() { + inputConfig.numberOfEvents = 2; + inputConfig.device = TEST_INPUT_DEVICE; + inputConfig.code = EVENT_CODE; + inputConfig.enabled = true; + inputConfig.timeWindowMs = 500; + + // fill simulated events with init values + ie[0].time.tv_sec = 946707544; + ie[0].time.tv_usec = 0; + ie[0].type = EVENT_TYPE; + ie[0].code = EVENT_CODE; + ie[0].value = EVENT_BUTTON_RELEASED; + + ie[1].time.tv_sec = 946707544; + ie[1].time.tv_usec = 0; + ie[1].type = 0; + ie[1].code = 0; + ie[1].value = 0; + + resetCounter(); + remove(TEST_INPUT_DEVICE); + mkfifo(TEST_INPUT_DEVICE, 0777); + } + ~Fixture() { + remove(TEST_INPUT_DEVICE); + resetCounter(); + } +}; + +} // namespace + +BOOST_AUTO_TEST_CASE(Config_OK) +{ + Fixture f; + + BOOST_REQUIRE_NO_THROW(InputMonitor inputMonitor(f.inputConfig, callbackEmpty)); +} + +BOOST_AUTO_TEST_CASE(Config_numberOfEventsTooHigh) +{ + Fixture f; + f.inputConfig.numberOfEvents = 100; + + BOOST_REQUIRE_THROW(InputMonitor inputMonitor(f.inputConfig, callbackEmpty), + InputMonitorException); +} + +BOOST_AUTO_TEST_CASE(Config_timeWindowMsTooHigh) +{ + Fixture f; + f.inputConfig.timeWindowMs = 50000; + + BOOST_REQUIRE_THROW(InputMonitor inputMonitor(f.inputConfig, callbackEmpty), + InputMonitorException); +} + +BOOST_AUTO_TEST_CASE(Config_deviceFilePathNotExisting) +{ + Fixture f; + f.inputConfig.device = std::string(TEST_INPUT_DEVICE) + "notexisting"; + + BOOST_REQUIRE_THROW(InputMonitor inputMonitor(f.inputConfig, callbackEmpty), + InputMonitorException); +} + +// ============================================================================================ +// All of the following tests are based on the (almost) the same scenario: +// 1) set up input monitor (create InputMonitor instance + register callback) +// 2) simulate an event(s) +// a) prepare an example sequence of event(s) to trigger the callback (one or more times, +// depending on the test purpose) +// b) send it to the device +// 3) verify that callback was triggered (one or more times accordingly) +// +// Button press + release events are simulated based on logs gathered from working system. +// Example log: +// +// // button pressed +// Event detected [gpio-keys.4]: +// time: 946691112.844176 sec +// type, code, value: 1, 139, 1 +// Event detected [gpio-keys.4]: +// time: 946691112.844176 sec +// type, code, value: 0, 0, 0 +// +// // button released +// Event detected [gpio-keys.4]: +// time: 946691113.384301 sec +// type, code, value: 1, 139, 0 +// Event detected [gpio-keys.4]: +// time: 946691113.384301 sec +// type, code, value: 0, 0, 0 +// +// +// ============================================================================================ + +void sendEvents(unsigned int noOfEvents) +{ + Fixture f; + Latch eventLatch; + + std::unique_ptr inputMonitor; + BOOST_REQUIRE_NO_THROW(inputMonitor.reset(new InputMonitor(f.inputConfig, + [&] { callbackCounter(); + if (getCounter() == noOfEvents) { + eventLatch.set(); + } + }))); + + int fd = open(TEST_INPUT_DEVICE, O_WRONLY); + + for (unsigned int i = 0; i < noOfEvents * f.inputConfig.numberOfEvents; ++i) { + // button pressed event + f.ie[0].value = EVENT_BUTTON_PRESSED; + f.ie[0].time.tv_usec += 5; + f.ie[1].time.tv_usec += 5; + ssize_t ret = safeWrite(fd, f.ie, 2 * sizeof(struct input_event)); + BOOST_CHECK(ret > 0); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + // button released event + f.ie[0].value = EVENT_BUTTON_RELEASED; + f.ie[0].time.tv_usec += 5; + f.ie[1].time.tv_usec += 5; + ret = safeWrite(fd, f.ie, 2 * sizeof(struct input_event)); + BOOST_CHECK(ret > 0); + } + + close(fd); + + BOOST_CHECK(eventLatch.wait(SINGLE_EVENT_TIMEOUT * noOfEvents)); + + // extra time to make sure, that no more events are read + std::this_thread::sleep_for(std::chrono::milliseconds(SINGLE_EVENT_TIMEOUT)); + + BOOST_CHECK(getCounter() == noOfEvents); +} + +BOOST_AUTO_TEST_CASE(Event_oneAtATime) +{ + sendEvents(ONE_EVENT); +} + +BOOST_AUTO_TEST_CASE(Event_tenAtATime) +{ + sendEvents(TEN_EVENTS); +} + +void sendEventsWithPauses(unsigned int noOfEvents) +{ + Fixture f; + Latch eventLatch; + + std::unique_ptr inputMonitor; + BOOST_REQUIRE_NO_THROW(inputMonitor.reset(new InputMonitor(f.inputConfig, + [&] { callbackCounter(); + if (getCounter() == noOfEvents) { + eventLatch.set(); + } + }))); + + int fd = open(TEST_INPUT_DEVICE, O_WRONLY); + + for (unsigned int i = 0; i < noOfEvents * f.inputConfig.numberOfEvents; ++i) { + // button pressed event + f.ie[0].value = EVENT_BUTTON_PRESSED; + f.ie[0].time.tv_usec += 5; + f.ie[1].time.tv_usec += 5; + ssize_t ret = write(fd, f.ie, 2); // send first two bytes + BOOST_CHECK(ret > 0); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + ret = write(fd, &reinterpret_cast(f.ie)[2], 2 * sizeof(struct input_event) - 2); // send the remaining part + BOOST_CHECK(ret > 0); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + // button released event + f.ie[0].value = EVENT_BUTTON_RELEASED; + f.ie[0].time.tv_usec += 5; + f.ie[1].time.tv_usec += 5; + ret = write(fd, f.ie, 2 * sizeof(struct input_event)); + BOOST_CHECK(ret > 0); + } + + close(fd); + + BOOST_CHECK(eventLatch.wait(SINGLE_EVENT_TIMEOUT * noOfEvents)); + + // extra time to make sure, that no more events are read + std::this_thread::sleep_for(std::chrono::milliseconds(SINGLE_EVENT_TIMEOUT)); + + BOOST_CHECK(getCounter() == noOfEvents); +} + +BOOST_AUTO_TEST_CASE(Event_oneAtATimeWithPauses) +{ + sendEventsWithPauses(ONE_EVENT); +} + +BOOST_AUTO_TEST_CASE(Event_tenAtATimeWithPauses) +{ + sendEventsWithPauses(TEN_EVENTS); +} + + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 7b9ab5e61e18c0191c7002c33257348ee8dfccac Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 2 Jun 2014 16:20:54 +0200 Subject: [PATCH 14/16] Fix of InputMonitor rebase [Bug/Feature] Unit tests changed directories. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I6817a8bed4ca74e7ebe27cf87f6793da04853699 Signed-off-by: Jan Olszak --- {unit_tests => tests/unit_tests}/server/ut-input-monitor.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {unit_tests => tests/unit_tests}/server/ut-input-monitor.cpp (100%) diff --git a/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp similarity index 100% rename from unit_tests/server/ut-input-monitor.cpp rename to tests/unit_tests/server/ut-input-monitor.cpp -- 2.7.4 From 44103c620efdc6e9977ee83e6ae0666e4ced2376 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Fri, 23 May 2014 14:20:11 +0200 Subject: [PATCH 15/16] Make the code compatible with more compilers [Bug/Feature] Make the code compatible with more compilers. [Cause] N/A [Solution] Redefine some C++11 keywords. Remove some specific C++11 constructs not found in C++0x. Specific defines for various compilers and their versions. [Verification] Built with GCC 4.6, GCC 4.8 and CLANG 3.4 and run tests. Change-Id: I5ce7c2c3ca4372ec79b41facb1793c7df5b1f6b0 Signed-off-by: Lukasz Pawelczyk --- CMakeLists.txt | 15 ++++-- client/exception.hpp | 3 +- client/main.cpp | 3 +- common/base-exception.hpp | 4 +- common/config.hpp | 63 ++++++++++++++++++++++ common/config/configuration.cpp | 1 + common/config/exception.hpp | 3 +- common/dbus/connection.cpp | 3 ++ common/dbus/exception.hpp | 15 ++++-- common/libvirt/connection.cpp | 2 + common/libvirt/connection.hpp | 2 +- common/libvirt/domain.cpp | 3 +- common/libvirt/domain.hpp | 2 +- common/libvirt/exception.hpp | 3 +- common/libvirt/helpers.cpp | 1 + common/libvirt/network.cpp | 4 +- common/libvirt/network.hpp | 2 +- common/log/backend-journal.cpp | 1 + common/log/backend-stderr.cpp | 1 + common/log/ccolor.cpp | 1 + common/log/ccolor.hpp | 4 +- common/log/formatter.cpp | 1 + common/log/level.cpp | 1 + common/log/logger.cpp | 1 + common/utils/callback-guard.cpp | 7 ++- common/utils/exception.hpp | 3 +- common/utils/file-wait.cpp | 1 + common/utils/fs.cpp | 1 + common/utils/glib-loop.cpp | 1 + common/utils/latch.cpp | 1 + common/utils/paths.hpp | 6 ++- common/utils/typeinfo.cpp | 3 +- container-daemon/daemon-connection.cpp | 2 + container-daemon/daemon.cpp | 2 + container-daemon/exception.hpp | 3 +- container-daemon/main.cpp | 8 +-- container-daemon/runner.cpp | 2 + server/container-admin.cpp | 55 +++++++++++++------ server/container-admin.hpp | 60 ++++++++------------- server/container-connection-transport.cpp | 2 + server/container-connection.cpp | 2 + server/container.cpp | 2 + server/containers-manager.cpp | 5 +- server/exception.hpp | 12 +++-- server/main.cpp | 7 ++- server/server.cpp | 2 + tests/unit_tests/config/ut-configuration.cpp | 1 + tests/unit_tests/dbus/test-client.cpp | 2 + tests/unit_tests/dbus/test-server.cpp | 2 + tests/unit_tests/dbus/ut-connection.cpp | 1 + tests/unit_tests/libvirt/connection.cpp | 1 + tests/unit_tests/libvirt/domain.cpp | 1 + tests/unit_tests/libvirt/network.cpp | 1 + tests/unit_tests/log/ut-logger.cpp | 1 + tests/unit_tests/server/ut-container-admin.cpp | 43 +++++++-------- .../unit_tests/server/ut-container-connection.cpp | 1 + tests/unit_tests/server/ut-container.cpp | 1 + tests/unit_tests/server/ut-containers-manager.cpp | 1 + tests/unit_tests/server/ut-input-monitor.cpp | 1 + tests/unit_tests/server/ut-server.cpp | 2 + tests/unit_tests/ut.cpp | 2 + tests/unit_tests/utils/scoped-daemon.cpp | 2 + tests/unit_tests/utils/ut-callback-guard.cpp | 3 +- tests/unit_tests/utils/ut-fs.cpp | 1 + tests/unit_tests/utils/ut-glib-loop.cpp | 3 +- tests/unit_tests/utils/ut-paths.cpp | 1 + 66 files changed, 281 insertions(+), 116 deletions(-) create mode 100644 common/config.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c987dd..18786ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,14 +35,21 @@ IF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE) MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +# special case for a GCC < 4.7, assume rest is fine +IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) + SET(CXX_11_STD "c++0x") +else() + SET(CXX_11_STD "c++11") +endif() + SET(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg") -SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=c++11 -O0 -pg") +SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=${CXX_11_STD} -O0 -pg") SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb") -SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=c++11 -O0 -ggdb") +SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=${CXX_11_STD} -O0 -ggdb") SET(CMAKE_C_FLAGS_RELEASE "-g -O2 -DNDEBUG") -SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=c++11 -O2 -DNDEBUG") +SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=${CXX_11_STD} -O2 -DNDEBUG") SET(CMAKE_C_FLAGS_CCOV "-g -O2 --coverage") -SET(CMAKE_CXX_FLAGS_CCOV "-g -std=c++11 -O2 --coverage") +SET(CMAKE_CXX_FLAGS_CCOV "-g -std=${CXX_11_STD} -O2 --coverage") ADD_DEFINITIONS("-fPIC") # Position Independent Code ADD_DEFINITIONS("-Werror") # Make all warnings into errors diff --git a/client/exception.hpp b/client/exception.hpp index b458d59..b4420e8 100644 --- a/client/exception.hpp +++ b/client/exception.hpp @@ -36,7 +36,8 @@ namespace security_containers { * @brief Base class for exceptions in Security Containers Client */ struct ClientException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + ClientException(const std::string& error = "") : SecurityContainersException(error) {} }; diff --git a/client/main.cpp b/client/main.cpp index e21be98..1c02567 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -16,11 +16,12 @@ * limitations under the License */ - /** * @file * @author Jan Olszak (j.olszak@samsung.com) * @brief Main file for the Security Containers Client */ +#include "config.hpp" + #include "exception.hpp" diff --git a/common/base-exception.hpp b/common/base-exception.hpp index e9f12f8..15fd3e0 100644 --- a/common/base-exception.hpp +++ b/common/base-exception.hpp @@ -27,6 +27,7 @@ #define COMMON_BASE_EXCEPTION_HPP #include +#include namespace security_containers { @@ -36,9 +37,8 @@ namespace security_containers { * Base class security containers exceptions */ struct SecurityContainersException: public std::runtime_error { - using std::runtime_error::runtime_error; - SecurityContainersException() : std::runtime_error(std::string()) {} + SecurityContainersException(const std::string& error = "") : std::runtime_error(error) {} }; diff --git a/common/config.hpp b/common/config.hpp new file mode 100644 index 0000000..567ef8e --- /dev/null +++ b/common/config.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Pawelczyk (l.pawelczyk@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 Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com) + * @brief Configuration file for the code + */ + + +#ifndef COMMON_CONFIG_HPP +#define COMMON_CONFIG_HPP + + +#ifdef __clang__ +#define CLANG_VERSION (__clang__major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#endif // __clang__ + +#if defined __GNUC__ && !defined __clang__ // clang also defines GCC versions +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif // __GNUC__ + + +#ifdef GCC_VERSION + +#if GCC_VERSION < 40800 +// GCC 4.8 is the first where those defines are not required for +// std::this_thread::sleep_for() and ::yield(). They might exist though +// in previous versions depending on the build configuration of the GCC. +#ifndef _GLIBCXX_USE_NANOSLEEP +#define _GLIBCXX_USE_NANOSLEEP +#endif // _GLIBCXX_USE_NANOSLEEP +#ifndef _GLIBCXX_USE_SCHED_YIELD +#define _GLIBCXX_USE_SCHED_YIELD +#endif // _GLIBCXX_USE_SCHED_YIELD +#endif // GCC_VERSION < 40800 + +#if GCC_VERSION < 40700 +// Those appeared in 4.7 with full c++11 support +#define final +#define override +#define thread_local __thread // use GCC extension instead of C++11 +#endif // GCC_VERSION < 40700 + +#endif // GCC_VERSION + + +#endif // COMMON_CONFIG_HPP diff --git a/common/config/configuration.cpp b/common/config/configuration.cpp index fe22aa1..8e093a6 100644 --- a/common/config/configuration.cpp +++ b/common/config/configuration.cpp @@ -22,6 +22,7 @@ * @brief Helper class for parsing and storing configurations in JSON format. */ +#include "config.hpp" #include "log/logger.hpp" #include "config/configuration.hpp" #include "config/exception.hpp" diff --git a/common/config/exception.hpp b/common/config/exception.hpp index 0d0b014..aa644b1 100644 --- a/common/config/exception.hpp +++ b/common/config/exception.hpp @@ -39,7 +39,8 @@ namespace config { * e.g. syntax error */ struct ConfigException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + ConfigException(const std::string& error = "") : SecurityContainersException(error) {} }; diff --git a/common/dbus/connection.cpp b/common/dbus/connection.cpp index af48230..03513cc 100644 --- a/common/dbus/connection.cpp +++ b/common/dbus/connection.cpp @@ -22,6 +22,7 @@ * @brief Dbus connection class */ +#include "config.hpp" #include "dbus/connection.hpp" #include "dbus/exception.hpp" #include "utils/callback-wrapper.hpp" @@ -138,6 +139,8 @@ DbusConnection::DbusConnection(const std::string& address) 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, diff --git a/common/dbus/exception.hpp b/common/dbus/exception.hpp index 21f0506..32cf87c 100644 --- a/common/dbus/exception.hpp +++ b/common/dbus/exception.hpp @@ -37,35 +37,40 @@ namespace dbus { * Base class for dbus exceptions */ struct DbusException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + DbusException(const std::string& error = "") : SecurityContainersException(error) {} }; /** * Dbus IO exception (connection failed, connection lost, etc) */ struct DbusIOException: public DbusException { - using DbusException::DbusException; + + DbusIOException(const std::string& error = "") : DbusException(error) {} }; /** * Dbus operation failed exception */ struct DbusOperationException: public DbusException { - using DbusException::DbusException; + + DbusOperationException(const std::string& error = "") : DbusException(error) {} }; /** * Dbus custom exception triggered by user logic */ struct DbusCustomException: public DbusException { - using DbusException::DbusException; + + DbusCustomException(const std::string& error = "") : DbusException(error) {} }; /** * Dbus invalid argument exception */ struct DbusInvalidArgumentException: public DbusException { - using DbusException::DbusException; + + DbusInvalidArgumentException(const std::string& error = "") : DbusException(error) {} }; diff --git a/common/libvirt/connection.cpp b/common/libvirt/connection.cpp index 1fada98..a7eab47 100644 --- a/common/libvirt/connection.cpp +++ b/common/libvirt/connection.cpp @@ -22,6 +22,7 @@ * @brief Implementation of the class wrapping connection to libvirtd */ +#include "config.hpp" #include "log/logger.hpp" #include "libvirt/helpers.hpp" #include "libvirt/connection.hpp" @@ -33,6 +34,7 @@ namespace libvirt { LibvirtConnection::LibvirtConnection(const std::string& uri) + : mCon(NULL) { libvirtInitialize(); diff --git a/common/libvirt/connection.hpp b/common/libvirt/connection.hpp index 70cfa3d..e0e1520 100644 --- a/common/libvirt/connection.hpp +++ b/common/libvirt/connection.hpp @@ -54,7 +54,7 @@ public: operator bool() const; private: - virConnectPtr mCon = NULL; + virConnectPtr mCon; }; diff --git a/common/libvirt/domain.cpp b/common/libvirt/domain.cpp index ae25a02..e813d83 100644 --- a/common/libvirt/domain.cpp +++ b/common/libvirt/domain.cpp @@ -22,6 +22,7 @@ * @brief Implementation of the class wrapping libvirt domain */ +#include "config.hpp" #include "log/logger.hpp" #include "libvirt/domain.hpp" #include "libvirt/helpers.hpp" @@ -33,7 +34,7 @@ namespace libvirt { LibvirtDomain::LibvirtDomain(const std::string& configXML) - : mCon(LIBVIRT_LXC_ADDRESS) + : mCon(LIBVIRT_LXC_ADDRESS), mDom(NULL) { mDom = virDomainDefineXML(mCon.get(), configXML.c_str()); diff --git a/common/libvirt/domain.hpp b/common/libvirt/domain.hpp index 4e22a3f..6da6d48 100644 --- a/common/libvirt/domain.hpp +++ b/common/libvirt/domain.hpp @@ -55,7 +55,7 @@ public: private: LibvirtConnection mCon; - virDomainPtr mDom = NULL; + virDomainPtr mDom; }; diff --git a/common/libvirt/exception.hpp b/common/libvirt/exception.hpp index aea145e..f207b56 100644 --- a/common/libvirt/exception.hpp +++ b/common/libvirt/exception.hpp @@ -36,7 +36,8 @@ namespace security_containers { * Base class for exceptions in libvirt */ struct LibvirtOperationException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + LibvirtOperationException(const std::string& error = "") : SecurityContainersException(error) {} }; diff --git a/common/libvirt/helpers.cpp b/common/libvirt/helpers.cpp index 36b49e5..7948a6a 100644 --- a/common/libvirt/helpers.cpp +++ b/common/libvirt/helpers.cpp @@ -22,6 +22,7 @@ * @brief A function helpers for the libvirt library */ +#include "config.hpp" #include "libvirt/helpers.hpp" #include "log/logger.hpp" diff --git a/common/libvirt/network.cpp b/common/libvirt/network.cpp index fdb9126..8b0e37e 100644 --- a/common/libvirt/network.cpp +++ b/common/libvirt/network.cpp @@ -22,6 +22,8 @@ * @brief Implementation of the class wrapping libvirt network */ +#include "config.hpp" + #include "log/logger.hpp" #include "libvirt/network.hpp" #include "libvirt/helpers.hpp" @@ -33,7 +35,7 @@ namespace libvirt { LibvirtNetwork::LibvirtNetwork(const std::string& configXML) - : mCon(LIBVIRT_LXC_ADDRESS) + : mCon(LIBVIRT_LXC_ADDRESS), mNet(NULL) { mNet = virNetworkDefineXML(mCon.get(), configXML.c_str()); diff --git a/common/libvirt/network.hpp b/common/libvirt/network.hpp index 5c5626e..92a73da 100644 --- a/common/libvirt/network.hpp +++ b/common/libvirt/network.hpp @@ -52,7 +52,7 @@ public: private: LibvirtConnection mCon; - virNetworkPtr mNet = NULL; + virNetworkPtr mNet; }; diff --git a/common/log/backend-journal.cpp b/common/log/backend-journal.cpp index 7f43419..1f043c1 100644 --- a/common/log/backend-journal.cpp +++ b/common/log/backend-journal.cpp @@ -22,6 +22,7 @@ * @brief Systemd journal backend for logger */ +#include "config.hpp" #include "log/backend-journal.hpp" #define SD_JOURNAL_SUPPRESS_LOCATION diff --git a/common/log/backend-stderr.cpp b/common/log/backend-stderr.cpp index fe1c5bc..471106c 100644 --- a/common/log/backend-stderr.cpp +++ b/common/log/backend-stderr.cpp @@ -22,6 +22,7 @@ * @brief Stderr backend for logger */ +#include "config.hpp" #include "log/backend-stderr.hpp" #include "log/formatter.hpp" diff --git a/common/log/ccolor.cpp b/common/log/ccolor.cpp index 703fcfc..128f11f 100644 --- a/common/log/ccolor.cpp +++ b/common/log/ccolor.cpp @@ -22,6 +22,7 @@ * @brief Console color for StderrBackend logger */ +#include "config.hpp" #include "log/ccolor.hpp" #include diff --git a/common/log/ccolor.hpp b/common/log/ccolor.hpp index ef93146..dc37458 100644 --- a/common/log/ccolor.hpp +++ b/common/log/ccolor.hpp @@ -39,12 +39,12 @@ enum class Color : unsigned int { BLUE = 94, MAGENTA = 95, CYAN = 96, - WHITE = 97, + WHITE = 97 }; enum class Attributes : unsigned int { DEFAULT = 0, - BOLD = 1, + BOLD = 1 }; std::string getConsoleEscapeSequence(Attributes attr, Color color); diff --git a/common/log/formatter.cpp b/common/log/formatter.cpp index 1bfe905..c0b0f7c 100644 --- a/common/log/formatter.cpp +++ b/common/log/formatter.cpp @@ -22,6 +22,7 @@ * @brief Helper formatter for logger */ +#include "config.hpp" #include "log/formatter.hpp" #include "log/ccolor.hpp" diff --git a/common/log/level.cpp b/common/log/level.cpp index 5fc3c2a..3897726 100644 --- a/common/log/level.cpp +++ b/common/log/level.cpp @@ -22,6 +22,7 @@ * @brief Functions to handle LogLevel */ +#include "config.hpp" #include "log/level.hpp" diff --git a/common/log/logger.cpp b/common/log/logger.cpp index f834557..83298ed 100644 --- a/common/log/logger.cpp +++ b/common/log/logger.cpp @@ -22,6 +22,7 @@ * @brief Logger */ +#include "config.hpp" #include "log/logger.hpp" #include "log/formatter.hpp" #include "log/backend-null.hpp" diff --git a/common/utils/callback-guard.cpp b/common/utils/callback-guard.cpp index d1e7084..3a35098 100644 --- a/common/utils/callback-guard.cpp +++ b/common/utils/callback-guard.cpp @@ -22,7 +22,8 @@ * @brief Callback guard */ -#include "callback-guard.hpp" +#include "config.hpp" +#include "utils/callback-guard.hpp" #include "log/logger.hpp" #include @@ -36,6 +37,8 @@ namespace utils { // Reference counting class like shared_ptr but with the ability to wait for it. class CallbackGuard::SharedState { public: + SharedState() : mCounter(0) {} + void inc() { std::unique_lock lock(mMutex); @@ -65,7 +68,7 @@ public: private: std::mutex mMutex; std::condition_variable mEmptyCondition; - long mCounter = 0; + long mCounter; }; namespace { diff --git a/common/utils/exception.hpp b/common/utils/exception.hpp index 366da77..e093f90 100644 --- a/common/utils/exception.hpp +++ b/common/utils/exception.hpp @@ -36,7 +36,8 @@ namespace security_containers { * Base class for exceptions in utils */ struct UtilsException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + UtilsException(const std::string& error = "") : SecurityContainersException(error) {} }; diff --git a/common/utils/file-wait.cpp b/common/utils/file-wait.cpp index cc468e3..9f210f1 100644 --- a/common/utils/file-wait.cpp +++ b/common/utils/file-wait.cpp @@ -22,6 +22,7 @@ * @brief Wait for file utility function */ +#include "config.hpp" #include "utils/exception.hpp" #include "utils/file-wait.hpp" diff --git a/common/utils/fs.cpp b/common/utils/fs.cpp index c8e0029..6d2ce18 100644 --- a/common/utils/fs.cpp +++ b/common/utils/fs.cpp @@ -22,6 +22,7 @@ * @brief File utility functions */ +#include "config.hpp" #include "log/logger.hpp" #include "utils/fs.hpp" #include "utils/paths.hpp" diff --git a/common/utils/glib-loop.cpp b/common/utils/glib-loop.cpp index 193a25f..6a60778 100644 --- a/common/utils/glib-loop.cpp +++ b/common/utils/glib-loop.cpp @@ -22,6 +22,7 @@ * @brief C++ wrapper of glib main loop */ +#include "config.hpp" #include "utils/glib-loop.hpp" #include "utils/callback-wrapper.hpp" diff --git a/common/utils/latch.cpp b/common/utils/latch.cpp index a35aee5..2ae240d 100644 --- a/common/utils/latch.cpp +++ b/common/utils/latch.cpp @@ -22,6 +22,7 @@ * @brief Synchronization latch */ +#include "config.hpp" #include "utils/latch.hpp" #include diff --git a/common/utils/paths.hpp b/common/utils/paths.hpp index 5f1d110..e357c71 100644 --- a/common/utils/paths.hpp +++ b/common/utils/paths.hpp @@ -81,8 +81,10 @@ inline void removeDuplicateSlashes(std::string& path) inline void removeTrailingSlash(std::string& path) { - if (path.size() > 1 && *(path.end() - 1) == '/') { - path.pop_back(); + size_t size = path.size(); + + if (size > 1 && path[size - 1] == '/') { + path.resize(size - 1); } } diff --git a/common/utils/typeinfo.cpp b/common/utils/typeinfo.cpp index fa3f839..7fe08ad 100644 --- a/common/utils/typeinfo.cpp +++ b/common/utils/typeinfo.cpp @@ -22,7 +22,8 @@ * @brief Synchronization latch */ -#include "typeinfo.hpp" +#include "config.hpp" +#include "utils/typeinfo.hpp" #include #include diff --git a/container-daemon/daemon-connection.cpp b/container-daemon/daemon-connection.cpp index 714d987..4f66e37 100644 --- a/container-daemon/daemon-connection.cpp +++ b/container-daemon/daemon-connection.cpp @@ -22,6 +22,8 @@ * @brief Dbus API for the Container Daemon */ +#include "config.hpp" + #include "daemon-connection.hpp" #include "daemon-dbus-definitions.hpp" #include "exception.hpp" diff --git a/container-daemon/daemon.cpp b/container-daemon/daemon.cpp index 9dd1c7b..d79762f 100644 --- a/container-daemon/daemon.cpp +++ b/container-daemon/daemon.cpp @@ -22,6 +22,8 @@ * @brief Definition of the Daemon, implementation of the logic of the daemon. */ +#include "config.hpp" + #include "daemon.hpp" #include "log/logger.hpp" diff --git a/container-daemon/exception.hpp b/container-daemon/exception.hpp index 2cd4d12..898d202 100644 --- a/container-daemon/exception.hpp +++ b/container-daemon/exception.hpp @@ -36,7 +36,8 @@ namespace container_daemon { * Base class for exceptions in Security Containers Container Daemon */ struct ContainerDaemonException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + ContainerDaemonException(const std::string& error = "") : SecurityContainersException(error) {} }; diff --git a/container-daemon/main.cpp b/container-daemon/main.cpp index 769de69..8dcdbad 100644 --- a/container-daemon/main.cpp +++ b/container-daemon/main.cpp @@ -28,14 +28,16 @@ #define LOG_TO_CONSOLE #endif +#include "config.hpp" + +#include "exception.hpp" +#include "runner.hpp" + #include "log/logger.hpp" #include "log/backend-stderr.hpp" #include "log/backend-journal.hpp" #include "utils/typeinfo.hpp" -#include "exception.hpp" -#include "runner.hpp" - #include #include diff --git a/container-daemon/runner.cpp b/container-daemon/runner.cpp index 5c5f9b0..13d3f21 100644 --- a/container-daemon/runner.cpp +++ b/container-daemon/runner.cpp @@ -22,6 +22,8 @@ * @brief Definition of the Runner class, that manages daemon's lifetime */ +#include "config.hpp" + #include "runner.hpp" #include "daemon.hpp" diff --git a/server/container-admin.cpp b/server/container-admin.cpp index 657ab4f..ed7b878 100644 --- a/server/container-admin.cpp +++ b/server/container-admin.cpp @@ -22,6 +22,8 @@ * @brief Implementation of class for administrating one container */ +#include "config.hpp" + #include "container-admin.hpp" #include "exception.hpp" @@ -72,7 +74,7 @@ ContainerAdmin::ContainerAdmin(ContainerConfig& config) mDetachOnExit(false), mLifecycleCallbackId(-1), mRebootCallbackId(-1), - mNextIdForListener(0) + mNextIdForListener(1) { LOGD(mId << ": Instantiating ContainerAdmin object"); @@ -185,10 +187,10 @@ void ContainerAdmin::stop() } }; - ListenerId id = registerListener(setStopped, nullptr); + ListenerId id = registerLifecycleListener(setStopped, nullptr); shutdown(); bool stopped = stoppedOccured.wait(SHUTDOWN_WAIT); - removeListener(id); + removeListener(id); if (!stopped) { LOGW(mId << ": Gracefull shutdown timed out, the container is still running, destroying"); @@ -405,6 +407,39 @@ std::int64_t ContainerAdmin::getSchedulerQuota() return quota; } +ContainerAdmin::ListenerId ContainerAdmin::registerLifecycleListener(const ContainerAdmin::LifecycleListener& listener, + const utils::CallbackGuard::Tracker& tracker) +{ + + utils::CallbackWrapper wrap(listener, tracker); + + std::unique_lock lock(mListenerMutex); + unsigned int id = mNextIdForListener++; + mLifecycleListeners.insert(LifecycleListenerMap::value_type(id, std::move(wrap))); + + return id; +} + +ContainerAdmin::ListenerId ContainerAdmin::registerRebootListener(const ContainerAdmin::RebootListener& listener, + const utils::CallbackGuard::Tracker& tracker) +{ + + utils::CallbackWrapper wrap(listener, tracker); + + std::unique_lock lock(mListenerMutex); + unsigned int id = mNextIdForListener++; + mRebootListeners.insert(RebootListenerMap::value_type(id, std::move(wrap))); + + return id; +} + +void ContainerAdmin::removeListener(const ContainerAdmin::ListenerId id) +{ + std::unique_lock lock(mListenerMutex); + mLifecycleListeners.erase(id); + mRebootListeners.erase(id); +} + int ContainerAdmin::libvirtLifecycleCallback(virConnectPtr /*con*/, virDomainPtr /*dom*/, int event, @@ -444,19 +479,5 @@ void ContainerAdmin::libvirtRebootCallback(virConnectPtr /*con*/, } } -template<> -ContainerAdmin::ListenerMap& -ContainerAdmin::getListenerMap() -{ - return mLifecycleListeners; -} - -template<> -ContainerAdmin::ListenerMap& -ContainerAdmin::getListenerMap() -{ - return mRebootListeners; -} - } // namespace security_containers diff --git a/server/container-admin.hpp b/server/container-admin.hpp index ed1e00e..8b2ec42 100644 --- a/server/container-admin.hpp +++ b/server/container-admin.hpp @@ -58,6 +58,11 @@ public: typedef unsigned int ListenerId; /** + * An invalid ListenerId value. + */ + static const ListenerId LISTENER_ID_INVALID = 0; + + /** * A function type used for the lifecycle listener */ typedef std::function LifecycleListener; @@ -145,20 +150,28 @@ public: std::int64_t getSchedulerQuota(); /** - * Sets a listener for a specific event. + * Sets a listener for a lifecycle event. * It's a caller's responsibility to remove the listener * prior to destroying the object. * * @return listener ID that can be used to remove. */ - template - ListenerId registerListener(const Listener& listener, - const utils::CallbackGuard::Tracker& tracker); + ListenerId registerLifecycleListener(const LifecycleListener& listener, + const utils::CallbackGuard::Tracker& tracker); + + /** + * Sets a listener for a reboot event. + * It's a caller's responsibility to remove the listener + * prior to destroying the object. + * + * @return listener ID that can be used to remove. + */ + ListenerId registerRebootListener(const RebootListener& listener, + const utils::CallbackGuard::Tracker& tracker); /** * Remove a previously registered listener. */ - template void removeListener(const ListenerId id); private: @@ -189,42 +202,15 @@ private: // for handling external listeners triggered from libvirt callbacks // TODO, the Listener type might not be unique, reimplement using proper listeners - template - using ListenerMap = std::map>; + typedef std::map> LifecycleListenerMap; + typedef std::map> RebootListenerMap; std::mutex mListenerMutex; - std::atomic mNextIdForListener; - ListenerMap mLifecycleListeners; - ListenerMap mRebootListeners; - - template - ListenerMap& getListenerMap(); + unsigned int mNextIdForListener; + LifecycleListenerMap mLifecycleListeners; + RebootListenerMap mRebootListeners; }; -template -unsigned int ContainerAdmin::registerListener(const Listener& listener, - const utils::CallbackGuard::Tracker& tracker) -{ - - ListenerMap& map = getListenerMap(); - unsigned int id = mNextIdForListener++; - utils::CallbackWrapper wrap(listener, tracker); - - std::unique_lock lock(mListenerMutex); - map.emplace(id, std::move(wrap)); - - return id; -} - -template -void ContainerAdmin::removeListener(const ContainerAdmin::ListenerId id) -{ - ListenerMap& map = getListenerMap(); - - std::unique_lock lock(mListenerMutex); - map.erase(id); -} - } // namespace security_containers diff --git a/server/container-connection-transport.cpp b/server/container-connection-transport.cpp index 71594f6..9b8848d 100644 --- a/server/container-connection-transport.cpp +++ b/server/container-connection-transport.cpp @@ -22,6 +22,8 @@ * @brief Implementation of a class for communication transport between container and server */ +#include "config.hpp" + #include "container-connection-transport.hpp" #include "exception.hpp" diff --git a/server/container-connection.cpp b/server/container-connection.cpp index b1c1df0..9f8a417 100644 --- a/server/container-connection.cpp +++ b/server/container-connection.cpp @@ -22,6 +22,8 @@ * @brief Implementation of a class for communication between container and server */ +#include "config.hpp" + #include "container-connection.hpp" #include "container-dbus-definitions.hpp" #include "exception.hpp" diff --git a/server/container.cpp b/server/container.cpp index 6ce6f24..bb8bcd3 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -22,6 +22,8 @@ * @brief Implementation of class for managing one container */ +#include "config.hpp" + #include "container.hpp" #include "log/logger.hpp" diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index 20c1f98..3b14c1b 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -22,9 +22,12 @@ * @brief Definition of the class for managing containers */ +#include "config.hpp" + #include "containers-manager.hpp" #include "container-admin.hpp" #include "exception.hpp" + #include "utils/paths.hpp" #include "log/logger.hpp" @@ -54,7 +57,7 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet LOGD("Creating Container " << containerConfigPath); std::unique_ptr c(new Container(containerConfigPath)); std::string id = c->getId(); - mContainers.emplace(id, std::move(c)); + mContainers.insert(ContainerMap::value_type(id, std::move(c))); } LOGD("ContainersManager object instantiated"); diff --git a/server/exception.hpp b/server/exception.hpp index 3291f79..37fa45e 100644 --- a/server/exception.hpp +++ b/server/exception.hpp @@ -36,7 +36,8 @@ namespace security_containers { * Base class for exceptions in Security Containers Server */ struct ServerException: public SecurityContainersException { - using SecurityContainersException::SecurityContainersException; + + ServerException(const std::string& error = "") : SecurityContainersException(error) {} }; /** @@ -44,14 +45,16 @@ struct ServerException: public SecurityContainersException { * e.g. start, stop a container */ struct ContainerOperationException: public ServerException { - using ServerException::ServerException; + + ContainerOperationException(const std::string& error = "") : ServerException(error) {} }; /** * Exception during performing an operation on a container connection */ struct ContainerConnectionException: public ServerException { - using ServerException::ServerException; + + ContainerConnectionException(const std::string& error = "") : ServerException(error) {} }; /** @@ -59,7 +62,8 @@ struct ContainerConnectionException: public ServerException { * e.g. create channel, register callback etc. */ struct InputMonitorException: public ServerException { - using ServerException::ServerException; + + InputMonitorException(const std::string& error = "") : ServerException(error) {} }; diff --git a/server/main.cpp b/server/main.cpp index 395d936..521f683 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -28,12 +28,15 @@ #define LOG_TO_CONSOLE #endif +#include "config.hpp" + +#include "exception.hpp" +#include "server.hpp" + #include "log/logger.hpp" #include "log/backend-stderr.hpp" #include "log/backend-journal.hpp" #include "utils/typeinfo.hpp" -#include "exception.hpp" -#include "server.hpp" #include #include diff --git a/server/server.cpp b/server/server.cpp index 82d0a6d..d04d562 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -22,6 +22,8 @@ * @brief Server class definition */ +#include "config.hpp" + #include "server.hpp" #include "containers-manager.hpp" #include "exception.hpp" diff --git a/tests/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp index cbb84eb..470cbfd 100644 --- a/tests/unit_tests/config/ut-configuration.cpp +++ b/tests/unit_tests/config/ut-configuration.cpp @@ -23,6 +23,7 @@ * @brief Unit test of ConfigurationBase */ +#include "config.hpp" #include "ut.hpp" #include "config/configuration.hpp" diff --git a/tests/unit_tests/dbus/test-client.cpp b/tests/unit_tests/dbus/test-client.cpp index f056765..59b6adb 100644 --- a/tests/unit_tests/dbus/test-client.cpp +++ b/tests/unit_tests/dbus/test-client.cpp @@ -22,6 +22,8 @@ * @brief Example dbus api client */ +#include "config.hpp" + #include "dbus/test-client.hpp" #include "dbus/test-common.hpp" diff --git a/tests/unit_tests/dbus/test-server.cpp b/tests/unit_tests/dbus/test-server.cpp index aaa99b4..e245d4d 100644 --- a/tests/unit_tests/dbus/test-server.cpp +++ b/tests/unit_tests/dbus/test-server.cpp @@ -22,6 +22,8 @@ * @brief Example dbus api server */ +#include "config.hpp" + #include "dbus/test-server.hpp" #include "dbus/test-common.hpp" diff --git a/tests/unit_tests/dbus/ut-connection.cpp b/tests/unit_tests/dbus/ut-connection.cpp index 6687f03..eed9af7 100644 --- a/tests/unit_tests/dbus/ut-connection.cpp +++ b/tests/unit_tests/dbus/ut-connection.cpp @@ -22,6 +22,7 @@ * @brief Dbus connection unit tests */ +#include "config.hpp" #include "ut.hpp" #include "dbus/test-server.hpp" #include "dbus/test-client.hpp" diff --git a/tests/unit_tests/libvirt/connection.cpp b/tests/unit_tests/libvirt/connection.cpp index c4ba8ff..26f649b 100644 --- a/tests/unit_tests/libvirt/connection.cpp +++ b/tests/unit_tests/libvirt/connection.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the LibvirtConnection class */ +#include "config.hpp" #include "ut.hpp" #include "libvirt/connection.hpp" diff --git a/tests/unit_tests/libvirt/domain.cpp b/tests/unit_tests/libvirt/domain.cpp index 2ecbcc3..4046460 100644 --- a/tests/unit_tests/libvirt/domain.cpp +++ b/tests/unit_tests/libvirt/domain.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the LibvirtDomain class */ +#include "config.hpp" #include "ut.hpp" #include "libvirt/domain.hpp" diff --git a/tests/unit_tests/libvirt/network.cpp b/tests/unit_tests/libvirt/network.cpp index 7f862f7..04e396d 100644 --- a/tests/unit_tests/libvirt/network.cpp +++ b/tests/unit_tests/libvirt/network.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the LibvirtNetwork class */ +#include "config.hpp" #include "ut.hpp" #include "libvirt/network.hpp" diff --git a/tests/unit_tests/log/ut-logger.cpp b/tests/unit_tests/log/ut-logger.cpp index 696bda5..b4aeb5d 100644 --- a/tests/unit_tests/log/ut-logger.cpp +++ b/tests/unit_tests/log/ut-logger.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the log utility */ +#include "config.hpp" #include "ut.hpp" #include "log/logger.hpp" #include "log/formatter.hpp" diff --git a/tests/unit_tests/server/ut-container-admin.cpp b/tests/unit_tests/server/ut-container-admin.cpp index 5d4d09c..7d534d9 100644 --- a/tests/unit_tests/server/ut-container-admin.cpp +++ b/tests/unit_tests/server/ut-container-admin.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the ContainerAdmin class */ +#include "config.hpp" #include "ut.hpp" #include "container-admin.hpp" @@ -96,7 +97,7 @@ BOOST_AUTO_TEST_CASE(MissingConfigTest) BOOST_AUTO_TEST_CASE(StartTest) { utils::Latch booted; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -105,7 +106,7 @@ BOOST_AUTO_TEST_CASE(StartTest) booted.set(); } }; - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(bootedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(bootedListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); @@ -113,13 +114,13 @@ BOOST_AUTO_TEST_CASE(StartTest) BOOST_CHECK(booted.wait(WAIT_TIMEOUT)); BOOST_CHECK(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(ShutdownTest) { utils::Latch shutdown; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -132,20 +133,20 @@ BOOST_AUTO_TEST_CASE(ShutdownTest) BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); BOOST_REQUIRE(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(shutdownListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(shutdownListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.shutdown()); BOOST_CHECK(shutdown.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isStopped()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(DestroyTest) { utils::Latch destroyed; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -158,20 +159,20 @@ BOOST_AUTO_TEST_CASE(DestroyTest) BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); BOOST_REQUIRE(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(destroyedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(destroyedListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.destroy()); BOOST_CHECK(destroyed.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isStopped()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(StopShutdownTest) { utils::Latch shutdown; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -184,21 +185,21 @@ BOOST_AUTO_TEST_CASE(StopShutdownTest) BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); BOOST_REQUIRE(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(shutdownListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(shutdownListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.stop()); BOOST_CHECK(shutdown.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isStopped()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } // This test needs to wait for a shutdown timer in stop() method. This takes 10s+. BOOST_AUTO_TEST_CASE(StopDestroyTest) { utils::Latch destroyed; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_NO_SHUTDOWN_CONFIG_PATH); ContainerAdmin ca(config); @@ -211,20 +212,20 @@ BOOST_AUTO_TEST_CASE(StopDestroyTest) BOOST_REQUIRE_NO_THROW(ca.start()); ensureStarted(); BOOST_REQUIRE(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(destroyedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(destroyedListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.stop()); BOOST_CHECK(destroyed.wait(WAIT_STOP_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isStopped()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(SuspendTest) { utils::Latch paused; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -237,20 +238,20 @@ BOOST_AUTO_TEST_CASE(SuspendTest) BOOST_REQUIRE_NO_THROW(ca.start()) ensureStarted(); BOOST_REQUIRE(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(pausedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(pausedListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.suspend()); BOOST_CHECK(paused.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isRunning()); BOOST_CHECK(ca.isPaused()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(ResumeTest) { utils::Latch unpaused; - ContainerAdmin::ListenerId id; + ContainerAdmin::ListenerId id = ContainerAdmin::LISTENER_ID_INVALID; ContainerConfig config; config.parseFile(TEST_CONFIG_PATH); ContainerAdmin ca(config); @@ -265,14 +266,14 @@ BOOST_AUTO_TEST_CASE(ResumeTest) BOOST_REQUIRE(ca.isRunning()); BOOST_REQUIRE_NO_THROW(ca.suspend()) BOOST_REQUIRE(ca.isPaused()); - BOOST_REQUIRE_NO_THROW(id = ca.registerListener(unpausedListener, mGuard.spawn())); + BOOST_REQUIRE_NO_THROW(id = ca.registerLifecycleListener(unpausedListener, mGuard.spawn())); BOOST_REQUIRE_NO_THROW(ca.resume()); BOOST_CHECK(unpaused.wait(WAIT_TIMEOUT)); BOOST_CHECK(!ca.isPaused()); BOOST_CHECK(ca.isRunning()); - BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); + BOOST_REQUIRE_NO_THROW(ca.removeListener(id)); } BOOST_AUTO_TEST_CASE(SchedulerLevelTest) diff --git a/tests/unit_tests/server/ut-container-connection.cpp b/tests/unit_tests/server/ut-container-connection.cpp index 5f485f4..4b757a3 100644 --- a/tests/unit_tests/server/ut-container-connection.cpp +++ b/tests/unit_tests/server/ut-container-connection.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the ContainerConnection class */ +#include "config.hpp" #include "ut.hpp" #include "container-connection.hpp" diff --git a/tests/unit_tests/server/ut-container.cpp b/tests/unit_tests/server/ut-container.cpp index 09aa059..da6479e 100644 --- a/tests/unit_tests/server/ut-container.cpp +++ b/tests/unit_tests/server/ut-container.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the Container class */ +#include "config.hpp" #include "ut.hpp" #include "container.hpp" diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index b0a96db..7004148 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the ContainersManager class */ +#include "config.hpp" #include "ut.hpp" #include "containers-manager.hpp" diff --git a/tests/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp index 31b02ea..a31d783 100644 --- a/tests/unit_tests/server/ut-input-monitor.cpp +++ b/tests/unit_tests/server/ut-input-monitor.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the InputMonitor class */ +#include "config.hpp" #include "ut.hpp" #include "input-monitor.hpp" diff --git a/tests/unit_tests/server/ut-server.cpp b/tests/unit_tests/server/ut-server.cpp index a185cf0..d7393b7 100644 --- a/tests/unit_tests/server/ut-server.cpp +++ b/tests/unit_tests/server/ut-server.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of the Server class */ +#include "config.hpp" #include "ut.hpp" #include "server.hpp" @@ -32,6 +33,7 @@ #include #include + BOOST_AUTO_TEST_SUITE(ServerSuite) using namespace security_containers; diff --git a/tests/unit_tests/ut.cpp b/tests/unit_tests/ut.cpp index 0108456..de98558 100644 --- a/tests/unit_tests/ut.cpp +++ b/tests/unit_tests/ut.cpp @@ -23,6 +23,8 @@ * @brief Main file for the Security Containers Daemon unit tests */ +#include "config.hpp" + #include "log/logger.hpp" #include "log/backend-stderr.hpp" diff --git a/tests/unit_tests/utils/scoped-daemon.cpp b/tests/unit_tests/utils/scoped-daemon.cpp index ca4fec6..077e19a 100644 --- a/tests/unit_tests/utils/scoped-daemon.cpp +++ b/tests/unit_tests/utils/scoped-daemon.cpp @@ -22,6 +22,8 @@ * @brief Starts external daemon in constructor, stops it in destructor */ +#include "config.hpp" + #include "utils/scoped-daemon.hpp" #include "log/logger.hpp" diff --git a/tests/unit_tests/utils/ut-callback-guard.cpp b/tests/unit_tests/utils/ut-callback-guard.cpp index 429ed79..6a503b0 100644 --- a/tests/unit_tests/utils/ut-callback-guard.cpp +++ b/tests/unit_tests/utils/ut-callback-guard.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of callback guard */ +#include "config.hpp" #include "ut.hpp" #include "utils/callback-guard.hpp" @@ -71,7 +72,7 @@ BOOST_AUTO_TEST_CASE(ThreadTest) Latch trackerCreated; Latch trackerCanBeDestroyed; - std::future future = std::async(std::launch::async, [&] { + std::future future = std::async(std::launch::async, [&]() -> bool { CallbackGuard::Tracker tracker = guard.spawn(); trackerCreated.set(); if (!trackerCanBeDestroyed.wait(TIMEOUT)) { diff --git a/tests/unit_tests/utils/ut-fs.cpp b/tests/unit_tests/utils/ut-fs.cpp index 845b0a4..adc8797 100644 --- a/tests/unit_tests/utils/ut-fs.cpp +++ b/tests/unit_tests/utils/ut-fs.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of utils */ +#include "config.hpp" #include "ut.hpp" #include "utils/fs.hpp" diff --git a/tests/unit_tests/utils/ut-glib-loop.cpp b/tests/unit_tests/utils/ut-glib-loop.cpp index f34fdbc..63fc3ee 100644 --- a/tests/unit_tests/utils/ut-glib-loop.cpp +++ b/tests/unit_tests/utils/ut-glib-loop.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of glib-loop */ +#include "config.hpp" #include "ut.hpp" #include "utils/latch.hpp" @@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE(GlibTimerEventTest) CallbackGuard guard; Latch latch; - Glib::OnTimerEventCallback callback = [&] { + Glib::OnTimerEventCallback callback = [&]()->bool { static unsigned int counter = 0; latch.set(); if (++counter >= TIMER_NUMBER) { diff --git a/tests/unit_tests/utils/ut-paths.cpp b/tests/unit_tests/utils/ut-paths.cpp index 087a7ad..e32424b 100644 --- a/tests/unit_tests/utils/ut-paths.cpp +++ b/tests/unit_tests/utils/ut-paths.cpp @@ -23,6 +23,7 @@ * @brief Unit tests of utils */ +#include "config.hpp" #include "ut.hpp" #include "utils/paths.hpp" -- 2.7.4 From 486cd8b4004cebce5bcd39f391a80fa88039242a Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 3 Jun 2014 11:54:17 +0200 Subject: [PATCH 16/16] Make the code compatible with older glib versions [Bug/Feature] Make the code compatible with older glib versions. [Cause] N/A [Solution] Specific define for older glib versions. [Verification] Built and run tests. Change-Id: I65a16393fe3c266ca1b27bea166b1d2b2a41d0be Signed-off-by: Dariusz Michaluk --- common/utils/glib-loop.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/utils/glib-loop.cpp b/common/utils/glib-loop.cpp index 6a60778..a735e1e 100644 --- a/common/utils/glib-loop.cpp +++ b/common/utils/glib-loop.cpp @@ -26,6 +26,7 @@ #include "utils/glib-loop.hpp" #include "utils/callback-wrapper.hpp" +#include namespace security_containers { namespace utils { @@ -34,6 +35,9 @@ namespace utils { ScopedGlibLoop::ScopedGlibLoop() : mLoop(g_main_loop_new(NULL, FALSE), g_main_loop_unref) { +#if !GLIB_CHECK_VERSION(2,36,0) + g_type_init(); +#endif mLoopThread = std::thread([this] { g_main_loop_run(mLoop.get()); }); -- 2.7.4