#include <mutex>
#include <libvirt/virterror.h>
+#include <libvirt-glib/libvirt-glib-event.h>
namespace security_containers {
std::call_once(gInitFlag, []() {
virInitialize();
virSetErrorFunc(NULL, &libvirtErrorFunction);
+ gvir_event_register();
});
}
return "Libvirt error: " + std::string(error->message);
}
+std::string libvirtEventToString(const int eventId)
+{
+ switch(eventId) {
+ case VIR_DOMAIN_EVENT_DEFINED:
+ return "Defined";
+ case VIR_DOMAIN_EVENT_UNDEFINED:
+ return "Undefined";
+ case VIR_DOMAIN_EVENT_STARTED:
+ return "Started";
+ case VIR_DOMAIN_EVENT_SUSPENDED:
+ return "Suspended";
+ case VIR_DOMAIN_EVENT_RESUMED:
+ return "Resumed";
+ case VIR_DOMAIN_EVENT_STOPPED:
+ return "Stopped";
+ case VIR_DOMAIN_EVENT_SHUTDOWN:
+ return "Shutdown";
+ case VIR_DOMAIN_EVENT_PMSUSPENDED:
+ return "PM Suspended";
+ case VIR_DOMAIN_EVENT_CRASHED:
+ return "Crashed";
+ default:
+ return "Unknown EventId";
+ }
+}
+
+std::string libvirtEventDetailToString(const int eventId, const int detailId)
+{
+ switch (eventId) {
+ case VIR_DOMAIN_EVENT_DEFINED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_DEFINED_ADDED:
+ return "Added";
+ case VIR_DOMAIN_EVENT_DEFINED_UPDATED:
+ return "Updated";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_UNDEFINED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_UNDEFINED_REMOVED:
+ return "Removed";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_STARTED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_STARTED_BOOTED:
+ return "Booted";
+ case VIR_DOMAIN_EVENT_STARTED_MIGRATED:
+ return "Migrated";
+ case VIR_DOMAIN_EVENT_STARTED_RESTORED:
+ return "Restored";
+ case VIR_DOMAIN_EVENT_STARTED_FROM_SNAPSHOT:
+ return "From Snapshot";
+ case VIR_DOMAIN_EVENT_STARTED_WAKEUP:
+ return "Wakeup";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_SUSPENDED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_SUSPENDED_PAUSED:
+ return "Paused";
+ case VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED:
+ return "Migrated";
+ case VIR_DOMAIN_EVENT_SUSPENDED_IOERROR:
+ return "IO Error";
+ case VIR_DOMAIN_EVENT_SUSPENDED_WATCHDOG:
+ return "Watchdog";
+ case VIR_DOMAIN_EVENT_SUSPENDED_RESTORED:
+ return "Restored";
+ case VIR_DOMAIN_EVENT_SUSPENDED_FROM_SNAPSHOT:
+ return "From Snapshot";
+ case VIR_DOMAIN_EVENT_SUSPENDED_API_ERROR:
+ return "API Error";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_RESUMED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_RESUMED_UNPAUSED:
+ return "Unpaused";
+ case VIR_DOMAIN_EVENT_RESUMED_MIGRATED:
+ return "Migrated";
+ case VIR_DOMAIN_EVENT_RESUMED_FROM_SNAPSHOT:
+ return "From Snapshot";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_STOPPED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN:
+ return "Shutdown";
+ case VIR_DOMAIN_EVENT_STOPPED_DESTROYED:
+ return "Destroyed";
+ case VIR_DOMAIN_EVENT_STOPPED_CRASHED:
+ return "Crashed";
+ case VIR_DOMAIN_EVENT_STOPPED_MIGRATED:
+ return "Migrated";
+ case VIR_DOMAIN_EVENT_STOPPED_SAVED:
+ return "Failed";
+ case VIR_DOMAIN_EVENT_STOPPED_FAILED:
+ return "Failed";
+ case VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT:
+ return "From Snapshot";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_SHUTDOWN:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_SHUTDOWN_FINISHED:
+ return "Finished";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_PMSUSPENDED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_PMSUSPENDED_MEMORY:
+ return "Memory";
+ case VIR_DOMAIN_EVENT_PMSUSPENDED_DISK:
+ return "Disk";
+ default:
+ return "Unknown detail";
+ }
+ case VIR_DOMAIN_EVENT_CRASHED:
+ switch (detailId) {
+ case VIR_DOMAIN_EVENT_CRASHED_PANICKED:
+ return "Panicked";
+ default:
+ return "Unknown detail";
+ }
+ default:
+ return "Unknown event";
+ }
+}
+
} // namespace libvirt
} // namespace security_containers
*/
std::string libvirtFormatError(void);
+/**
+ * Converts an event ID to an event name.
+ */
+std::string libvirtEventToString(const int event);
+
+/**
+ * Converts an event's detail ID to an event's detail name.
+ */
+std::string libvirtEventDetailToString(const int event, const int detail);
+
} // namespace libvirt
} // namespace security_containers
#include <cassert>
#include <sstream>
#include <iomanip>
+#include <thread>
+#include <atomic>
namespace security_containers {
namespace log {
const int TIME_COLUMN_LENGTH = 12;
const int SEVERITY_COLUMN_LENGTH = 8;
-const int FILE_COLUMN_LENGTH = 52;
+const int THREAD_COLUMN_LENGTH = 3;
+const int FILE_COLUMN_LENGTH = 60;
+
+std::atomic<unsigned int> gNextThreadId(1);
+thread_local unsigned int gThisThreadId(0);
+
+unsigned int LogFormatter::getCurrentThread(void)
+{
+ unsigned int id = gThisThreadId;
+ if (id == 0) {
+ gThisThreadId = id = gNextThreadId++;
+ }
+
+ return id;
+}
std::string LogFormatter::getCurrentTime(void)
{
std::ostringstream logLine;
logLine << getCurrentTime() << ' '
<< std::left << std::setw(SEVERITY_COLUMN_LENGTH) << '[' + toString(logLevel) + ']'
+ << std::right << std::setw(THREAD_COLUMN_LENGTH) << getCurrentThread() << ": "
<< std::left << std::setw(FILE_COLUMN_LENGTH)
<< file + ':' + std::to_string(line) + ' ' + func + ':';
return logLine.str();
} // namespace log
} // namespace security_containers
-
class LogFormatter {
public:
+ static unsigned int getCurrentThread(void);
static std::string getCurrentTime(void);
static std::string getConsoleColor(LogLevel logLevel);
static std::string getDefaultConsoleColor(void);
BuildRequires: libjson-devel
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libsystemd-journal)
+BuildRequires: pkgconfig(libvirt-glib-1.0)
%description
This package provides a daemon used to manage containers - start, stop and switch
## Link libraries ##############################################################
FIND_PACKAGE (Boost COMPONENTS program_options REQUIRED)
-PKG_CHECK_MODULES(SERVER_DEPS REQUIRED libvirt json gio-2.0 libsystemd-journal)
+PKG_CHECK_MODULES(SERVER_DEPS REQUIRED libvirt libvirt-glib-1.0 json gio-2.0 libsystemd-journal)
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${SERVER_CODENAME} ${SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES})
#include "libvirt/helpers.hpp"
#include "log/logger.hpp"
#include "utils/fs.hpp"
+#include "utils/latch.hpp"
+#include "utils/callback-wrapper.hpp"
#include <cassert>
#include <cstring>
namespace {
+// TODO: this should be in container's configuration file
+const int SHUTDOWN_WAIT = 10 * 1000;
+
std::string getDomainName(virDomainPtr dom)
{
assert(dom != NULL);
const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
ContainerAdmin::ContainerAdmin(ContainerConfig& config)
- : mConfig(config), mDom(utils::readFileContent(mConfig.config)), mId(getDomainName(mDom.get()))
+ : mConfig(config),
+ mDom(utils::readFileContent(mConfig.config)),
+ mId(getDomainName(mDom.get())),
+ mLifecycleCallbackId(-1),
+ mRebootCallbackId(-1),
+ mNextIdForListener(0)
{
LOGD(mId << ": Instantiating ContainerAdmin object");
+
+ // ContainerAdmin owns those callbacks
+ mLifecycleCallbackId = virConnectDomainEventRegisterAny(virDomainGetConnect(mDom.get()),
+ mDom.get(),
+ VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+ VIR_DOMAIN_EVENT_CALLBACK(&ContainerAdmin::libvirtLifecycleCallback),
+ utils::createCallbackWrapper(this, mLibvirtGuard.spawn()),
+ &utils::deleteCallbackWrapper<ContainerAdmin*>);
+
+ if (mLifecycleCallbackId < 0) {
+ LOGE(mId << ": Failed to register a libvirt lifecycle callback");
+ throw ContainerOperationException(mId + ": Failed to register a libvirt lifecycle callback");
+ }
+
+ mRebootCallbackId = virConnectDomainEventRegisterAny(virDomainGetConnect(mDom.get()),
+ mDom.get(),
+ VIR_DOMAIN_EVENT_ID_REBOOT,
+ VIR_DOMAIN_EVENT_CALLBACK(&ContainerAdmin::libvirtRebootCallback),
+ utils::createCallbackWrapper(this, mLibvirtGuard.spawn()),
+ &utils::deleteCallbackWrapper<ContainerAdmin*>);
+
+ if (mRebootCallbackId < 0) {
+ LOGE(mId << ": Failed to register a libvirt reboot callback");
+ virConnectDomainEventDeregisterAny(virDomainGetConnect(mDom.get()),
+ mLifecycleCallbackId);
+ throw ContainerOperationException(mId + ": Failed to register a libvirt reboot callback");
+ }
}
ContainerAdmin::~ContainerAdmin()
{
- // Try to shutdown
- LOGD(mId << ": Destroying ContainerAdmin object...");
- try {
- shutdown();
- } catch (ServerException&) {}
+ // Deregister callbacks
+ if (mLifecycleCallbackId >= 0) {
+ virConnectDomainEventDeregisterAny(virDomainGetConnect(mDom.get()),
+ mLifecycleCallbackId);
+ }
+ if (mRebootCallbackId >= 0) {
+ virConnectDomainEventDeregisterAny(virDomainGetConnect(mDom.get()),
+ mRebootCallbackId);
+ }
// Try to forcefully stop
+ LOGD(mId << ": Destroying ContainerAdmin object...");
try {
- stop();
+ destroy();
} catch (ServerException&) {
- LOGE(mId << ": Failed to destroy the container!");
+ LOGE(mId << ": Failed to destroy the container");
}
LOGD(mId << ": ContainerAdmin object destroyed");
{
assert(mDom);
- LOGD(mId << ": Stopping...");
+ LOGD(mId << ": Stopping procedure started...");
+ if (isStopped()) {
+ LOGD(mId << ": Already crashed/down/off - nothing to do");
+ return;
+ }
+
+ utils::Latch stoppedOccured;
+
+ LifecycleListener setStopped = [&](const int eventId, const int detailId) {
+ if (eventId == VIR_DOMAIN_EVENT_STOPPED) {
+ if (detailId != VIR_DOMAIN_EVENT_STOPPED_SHUTDOWN) {
+ LOGW(mId << ": shutdown requested, but the container stopped with a different status: "
+ << libvirt::libvirtEventDetailToString(eventId, detailId));
+ }
+ stoppedOccured.set();
+ }
+ };
+
+ ListenerId id = registerListener(setStopped, nullptr);
+ shutdown();
+ bool stopped = stoppedOccured.wait(SHUTDOWN_WAIT);
+ removeListener<LifecycleListener>(id);
+
+ if (!stopped) {
+ LOGD(mId << ": waiting for shutdown timed out, destroying");
+ destroy();
+ }
+
+ LOGD(mId << ": Stopping procedure ended");
+}
+
+
+void ContainerAdmin::destroy()
+{
+ assert(mDom);
+
+ LOGD(mId << ": Destroying...");
if (isStopped()) {
- LOGD(mId << ": Already crashed/down/off - nothing to do...");
+ LOGD(mId << ": Already crashed/down/off - nothing to do");
return;
}
+ setSchedulerLevel(SchedulerLevel::FOREGROUND);
+
// Forceful termination of the guest
u_int flags = VIR_DOMAIN_DESTROY_DEFAULT;
if (virDomainDestroyFlags(mDom.get(), flags) < 0) {
- LOGE(mId << ": Error while stopping the container:\n"
+ LOGE(mId << ": Error while destroying the container:\n"
<< libvirt::libvirtFormatError());
throw ContainerOperationException();
}
- LOGD(mId << ": Stopped");
+ LOGD(mId << ": Destroyed");
}
LOGD(mId << ": Shutting down...");
if (isStopped()) {
- LOGD(mId << ": Already crashed/down/off - nothing to do...");
+ LOGD(mId << ": Already crashed/down/off - nothing to do");
return;
}
- resume();
+ setSchedulerLevel(SchedulerLevel::FOREGROUND);
if (virDomainShutdown(mDom.get()) < 0) {
LOGE(mId << ": Error while shutting down the container:\n"
throw ContainerOperationException();
}
- LOGD(mId << ": Shut down");
+ LOGD(mId << ": Shut down initiated (async)");
}
return quota;
}
+int ContainerAdmin::libvirtLifecycleCallback(virConnectPtr /*con*/,
+ virDomainPtr /*dom*/,
+ int event,
+ int detail,
+ void* opaque)
+{
+ ContainerAdmin* thisPtr = utils::getCallbackFromPointer<ContainerAdmin*>(opaque);
+
+ LOGI(thisPtr->getId()
+ << ": Lifecycle event: "
+ << libvirt::libvirtEventToString(event)
+ << ": "
+ << libvirt::libvirtEventDetailToString(event, detail));
+
+ std::unique_lock<std::mutex> lock(thisPtr->mListenerMutex);
+ for (auto& it : thisPtr->mLifecycleListeners) {
+ LifecycleListener f = it.second.get();
+ f(event, detail);
+ }
+
+ // ignored, libvirt's legacy
+ return 0;
+}
+
+void ContainerAdmin::libvirtRebootCallback(virConnectPtr /*con*/,
+ virDomainPtr /*dom*/,
+ void* opaque)
+{
+ ContainerAdmin* thisPtr = utils::getCallbackFromPointer<ContainerAdmin*>(opaque);
+
+ LOGI(thisPtr->getId() << ": Reboot event");
+
+ std::unique_lock<std::mutex> lock(thisPtr->mListenerMutex);
+ for (auto& it : thisPtr->mRebootListeners) {
+ RebootListener f = it.second.get();
+ f();
+ }
+}
+
+template<>
+ContainerAdmin::ListenerMap<ContainerAdmin::LifecycleListener>&
+ContainerAdmin::getListenerMap<ContainerAdmin::LifecycleListener>()
+{
+ return mLifecycleListeners;
+}
+
+template<>
+ContainerAdmin::ListenerMap<ContainerAdmin::RebootListener>&
+ContainerAdmin::getListenerMap<ContainerAdmin::RebootListener>()
+{
+ return mRebootListeners;
+}
+
} // namespace security_containers
#include "container-config.hpp"
+#include "utils/callback-guard.hpp"
+#include "utils/callback-wrapper.hpp"
#include "libvirt/connection.hpp"
#include "libvirt/domain.hpp"
+#include <map>
+#include <mutex>
+#include <atomic>
#include <string>
#include <cstdint>
#include <libvirt/libvirt.h>
class ContainerAdmin {
public:
+ /**
+ * A listener ID type.
+ */
+ typedef unsigned int ListenerId;
+
+ /**
+ * A function type used for the lifecycle listener
+ */
+ typedef std::function<void(const int eventId, const int detailId)> LifecycleListener;
+
+ /**
+ * A function type used for the reboot listener
+ */
+ typedef std::function<void()> RebootListener;
+
ContainerAdmin(ContainerConfig& config);
virtual ~ContainerAdmin();
void start();
/**
- * Forcefully stop the container.
+ * Try to shutdown the container, if failed, destroy it.
*/
void stop();
/**
+ * Forcefully stop the container.
+ */
+ void destroy();
+
+ /**
* Gracefully shutdown the container.
- * This method will NOT block until container is shut down,
- * because some configurations may ignore this.
+ * This method will NOT block until container is shut down.
*/
void shutdown();
*/
std::int64_t getSchedulerQuota();
+ /**
+ * Sets a listener for a specific 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 <typename Listener>
+ ListenerId registerListener(const Listener& listener,
+ const utils::CallbackGuard::Tracker& tracker);
+
+ /**
+ * Remove a previously registered listener.
+ */
+ template <typename Listener>
+ void removeListener(const ListenerId id);
+
private:
ContainerConfig& mConfig;
libvirt::LibvirtDomain mDom;
int getState(); // get the libvirt's domain state
void setSchedulerParams(std::uint64_t cpuShares, std::uint64_t vcpuPeriod, std::int64_t vcpuQuota);
+ // for handling libvirt callbacks
+ utils::CallbackGuard mLibvirtGuard;
+ int mLifecycleCallbackId;
+ int mRebootCallbackId;
+
+ // virConnectDomainEventCallback
+ static int libvirtLifecycleCallback(virConnectPtr con,
+ virDomainPtr dom,
+ int event,
+ int detail,
+ void* opaque);
+
+ // virConnectDomainEventGenericCallback
+ static void libvirtRebootCallback(virConnectPtr con,
+ virDomainPtr dom,
+ void* opaque);
+
+ // for handling external listeners triggered from libvirt callbacks
+ // TODO, the Listener type might not be unique, reimplement using proper listeners
+ template <typename Listener>
+ using ListenerMap = std::map<ListenerId, utils::CallbackWrapper<Listener>>;
+
+ std::mutex mListenerMutex;
+ std::atomic<unsigned int> mNextIdForListener;
+ ListenerMap<LifecycleListener> mLifecycleListeners;
+ ListenerMap<RebootListener> mRebootListeners;
+
+ template <typename Listener>
+ ListenerMap<Listener>& getListenerMap();
};
+template <typename Listener>
+unsigned int ContainerAdmin::registerListener(const Listener& listener,
+ const utils::CallbackGuard::Tracker& tracker)
+{
+ ListenerMap<Listener>& map = getListenerMap<Listener>();
+ unsigned int id = mNextIdForListener++;
+ utils::CallbackWrapper<Listener> wrap(listener, tracker);
+
+ std::unique_lock<std::mutex> lock(mListenerMutex);
+ map.emplace(id, std::move(wrap));
+
+ return id;
}
+template <typename Listener>
+void ContainerAdmin::removeListener(const ContainerAdmin::ListenerId id)
+{
+ ListenerMap<Listener>& map = getListenerMap<Listener>();
+
+ std::unique_lock<std::mutex> lock(mListenerMutex);
+ map.erase(id);
+}
+
+
+} // namespace security_containers
+
#endif // SERVER_CONTAINER_ADMIN_HPP
// Timeout in ms for waiting for dbus transport.
// Should be very long to ensure dbus in container is ready.
+// TODO: this should be in container's configuration file
const unsigned int TRANSPORT_READY_TIMEOUT = 2 * 60 * 1000;
} // namespace
// Timeout in ms for waiting for dbus name.
// Can happen if glib loop is busy or not present.
+// TODO: this should be in container's configuration file
const unsigned int NAME_ACQUIRED_TIMEOUT = 5 * 1000;
} // namespace
// Send to the background only after we're connected,
// otherwise it'd take ages.
- LOGD(getId() << ": Sending to the background");
+ LOGD(getId() << ": DBUS connected, sending to the background");
goBackground();
}
address = mConnectionTransport->acquireAddress();
} catch (SecurityContainersException&) {
LOGE(getId() << "The socket does not exist anymore, something went terribly wrong, stopping the container");
- stop(); // TODO: shutdownOrStop()
+ stop();
return;
}
LOGI(getId() << ": Reconnected");
} catch (SecurityContainersException&) {
LOGE(getId() << ": Reconnecting to the DBUS has failed, stopping the container");
- stop(); // TODO: shutdownOrStop()
+ stop();
return;
}
}
void start();
/**
- * Forcefully stop the container.
+ * Try to shutdown the container, if failed, destroy it.
*/
void stop();
{
LOGD("Destroying ContainersManager object...");
try {
- stopAll(); // TODO: shutdownOrStop()
+ stopAll();
} catch (ServerException&) {
LOGE("Failed to stop all of the containers");
}
if (container.first == mConfig.foregroundId) {
isForegroundFound = true;
+ LOGI(container.second->getId() << ": set as the foreground container");
container.second->goForeground();
}
}
});
mConfig.foregroundId = foregroundIterator->second->getId();
+ LOGI(mConfig.foregroundId << ": no foreground container configured, setting one with highest priority");
foregroundIterator->second->goForeground();
}
}
## Link libraries ##############################################################
FIND_PACKAGE (Boost COMPONENTS unit_test_framework REQUIRED)
-PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED libvirt json gio-2.0 libsystemd-journal)
+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})
INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES})
<name>ut-container-admin-test</name>
<uuid>a1299273-bce2-4d1f-8369-54b75a791279</uuid>
<memory>102400</memory>
- <on_poweroff>destroy</on_poweroff>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<name>ut-container-test-dbus</name>
<uuid>35bb7989-f222-4b63-b0b1-facbdb05b495</uuid>
<memory>102400</memory>
- <on_poweroff>destroy</on_poweroff>
<os>
<type>exe</type>
- <init>/bin/dbus-daemon</init>
- <initarg>--config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container/ut-dbus.conf</initarg>
- <initarg>--nofork</initarg>
+ <init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; /bin/dbus-daemon --config-file=@SC_TEST_CONFIG_INSTALL_DIR@/server/ut-container/ut-dbus.conf --fork; read</initarg>
</os>
<devices>
<console type="pty"/>
<name>ut-container-test</name>
<uuid>be2e7a5e-c59f-4264-aeab-390cedf47922</uuid>
<memory>102400</memory>
- <on_poweroff>destroy</on_poweroff>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
<os>
<type>exe</type>
<init>/bin/sh</init>
+ <initarg>-c</initarg>
+ <initarg>trap exit SIGTERM; read</initarg>
</os>
<devices>
<console type="pty"/>
#include "container-admin.hpp"
#include "exception.hpp"
+#include "utils/glib-loop.hpp"
#include "utils/exception.hpp"
#include "libvirt/exception.hpp"
BOOST_AUTO_TEST_CASE(StopTest)
{
+ utils::ScopedGlibLoop loop;
+
ContainerConfig config; config.parseFile(TEST_CONFIG_PATH);
ContainerAdmin ca(config);
BOOST_REQUIRE_NO_THROW(ca.start());
#include <string>
-BOOST_AUTO_TEST_SUITE(ContainerSuite)
-
using namespace security_containers;
using namespace security_containers::config;
-using namespace security_containers::utils;
namespace {
const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-container/containers/buggy.conf";
const std::string MISSING_CONFIG_PATH = "/this/is/a/missing/file/path/config.conf";
+struct Fixture {
+ utils::ScopedGlibLoop loop;
+};
+
} // namespace
+
+BOOST_FIXTURE_TEST_SUITE(ContainerSuite, Fixture)
+
BOOST_AUTO_TEST_CASE(ConstructorTest)
{
BOOST_REQUIRE_NO_THROW(Container c(TEST_CONFIG_PATH));
BOOST_AUTO_TEST_CASE(StartStopTest)
{
- ScopedGlibLoop loop;
-
std::unique_ptr<Container> c(new Container(TEST_CONFIG_PATH));
BOOST_REQUIRE_NO_THROW(c->start());
BOOST_REQUIRE_NO_THROW(c->stop());
BOOST_AUTO_TEST_CASE(DbusConnectionTest)
{
- ScopedGlibLoop loop;
-
std::unique_ptr<Container> c;
BOOST_REQUIRE_NO_THROW(c.reset(new Container(TEST_DBUS_CONFIG_PATH)));
BOOST_REQUIRE_NO_THROW(c->start());
#include "containers-manager.hpp"
#include "exception.hpp"
+#include "utils/glib-loop.hpp"
+
#include <memory>
#include <string>
-BOOST_AUTO_TEST_SUITE(ContainersManagerSuite)
-
using namespace security_containers;
using namespace security_containers::config;
+namespace {
+
const std::string TEST_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/test-daemon.conf";
const std::string BUGGY_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-daemon.conf";
const std::string BUGGY_FOREGROUND_CONFIG_PATH = SC_TEST_CONFIG_INSTALL_DIR "/server/ut-containers-manager/buggy-foreground-daemon.conf";
const std::string MISSING_CONFIG_PATH = "/this/is/a/missing/file/path/missing-daemon.conf";
+struct Fixture {
+ utils::ScopedGlibLoop loop;
+};
+
+} // namespace
+
+
+BOOST_FIXTURE_TEST_SUITE(ContainersManagerSuite, Fixture)
BOOST_AUTO_TEST_CASE(ConstructorTest)
{