--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * @file
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Lxc domain
+ */
+
+#include "config.hpp"
+#include "logger/logger.hpp"
+#include "lxc/domain.hpp"
+#include "lxc/exception.hpp"
+
+#include <lxc/lxccontainer.h>
+#include <sys/stat.h>
+
+namespace security_containers {
+namespace lxc {
+
+
+LxcDomain::LxcDomain(const std::string& lxcPath, const std::string& domainName)
+ : mContainer(nullptr)
+{
+ mContainer = lxc_container_new(domainName.c_str(), lxcPath.c_str());
+ if (!mContainer) {
+ LOGE("Could not initialize lxc domain " << domainName << " in path " << lxcPath);
+ throw LxcException("Could not initialize lxc domain");
+ }
+}
+
+LxcDomain::~LxcDomain()
+{
+ lxc_container_put(mContainer);
+}
+
+std::string LxcDomain::getName() const
+{
+ return mContainer->name;
+}
+
+std::string LxcDomain::getConfigItem(const std::string& key)
+{
+ char buffer[1024];
+ int len = mContainer->get_config_item(mContainer, key.c_str(), buffer, sizeof(buffer));
+ if (len < 0) {
+ LOGE("Key '" + key + "' not found in domain " + getName());
+ throw LxcException("Key not found");
+ }
+ return buffer;
+}
+
+bool LxcDomain::isDefined()
+{
+ return mContainer->is_defined(mContainer);
+}
+
+bool LxcDomain::isRunning()
+{
+ return mContainer->is_running(mContainer);
+}
+
+std::string LxcDomain::getState()
+{
+ return mContainer->state(mContainer);
+}
+
+void LxcDomain::create(const std::string& templatePath)
+{
+ if (!mContainer->create(mContainer, templatePath.c_str(), NULL, NULL, 0, NULL)) {
+ LOGE("Could not create domain " + getName());
+ throw LxcException("Could not create domain");
+ }
+}
+
+void LxcDomain::destroy()
+{
+ if (!mContainer->destroy(mContainer)) {
+ LOGE("Could not destroy domain " + getName());
+ throw LxcException("Could not destroy domain");
+ }
+}
+
+void LxcDomain::start(const char* argv[])
+{
+ if (!mContainer->start(mContainer, false, const_cast<char**>(argv))) {
+ LOGE("Could not start domain " + getName());
+ throw LxcException("Could not start domain");
+ }
+}
+
+void LxcDomain::stop()
+{
+ if (!mContainer->stop(mContainer)) {
+ LOGE("Could not stop domain " + getName());
+ throw LxcException("Stop domain failed");
+ }
+}
+
+void LxcDomain::reboot()
+{
+ if (!mContainer->reboot(mContainer)) {
+ LOGE("Could not reboot domain " + getName());
+ throw LxcException("Reboot domain failed");
+ }
+}
+
+void LxcDomain::shutdown(int timeout)
+{
+ if (!mContainer->shutdown(mContainer, timeout)) {
+ LOGE("Could not gracefully shutdown domain " + getName() + " in " << timeout << "s");
+ throw LxcException("Shutdown domain failed");
+ }
+}
+
+} // namespace lxc
+} // namespace security_containers
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * @file
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Lxc domain
+ */
+
+#ifndef COMMON_LXC_DOMAIN_HPP
+#define COMMON_LXC_DOMAIN_HPP
+
+#include <string>
+
+// fwd declaration of lxc internals
+struct lxc_container;
+
+namespace security_containers {
+namespace lxc {
+
+
+/**
+ * A class wwapping lxc container
+ */
+class LxcDomain {
+public:
+ LxcDomain(const std::string& lxcPath, const std::string& domainName);
+ ~LxcDomain();
+
+ LxcDomain(const LxcDomain&) = delete;
+ LxcDomain& operator=(const LxcDomain&) = delete;
+
+ std::string getName() const;
+
+ std::string getConfigItem(const std::string& key);
+
+ bool isDefined();
+ bool isRunning();
+
+ std::string getState();
+
+ void create(const std::string& templatePath);
+ void destroy();
+
+ void start(const char* argv[]);
+ void stop();
+ void reboot();
+ void shutdown(int timeout);
+private:
+ lxc_container* mContainer;
+};
+
+
+} // namespace lxc
+} // namespace security_containers
+
+
+#endif // COMMON_LXC_DOMAIN_HPP
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+/**
+ * @file
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Lxc exception
+ */
+
+
+#ifndef COMMON_LXC_EXCEPTION_HPP
+#define COMMON_LXC_EXCEPTION_HPP
+
+#include "base-exception.hpp"
+
+
+namespace security_containers {
+
+
+/**
+ * Base class for exceptions in utils
+ */
+struct LxcException: public SecurityContainersException {
+
+ LxcException(const std::string& error) : SecurityContainersException(error) {}
+};
+
+
+}
+
+
+#endif // COMMON_UTILS_EXCEPTION_HPP
Summary: Daemon for managing containers
BuildRequires: cmake
BuildRequires: boost-devel
-BuildRequires: libvirt-devel
BuildRequires: libjson-devel >= 0.10
BuildRequires: libcap-ng-devel
+BuildRequires: lxc-devel
BuildRequires: pkgconfig(libConfig)
BuildRequires: pkgconfig(libLogger)
BuildRequires: pkgconfig(libSimpleDbus)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libsystemd-journal)
-BuildRequires: pkgconfig(libvirt-glib-1.0)
BuildRequires: pkgconfig(sqlite3)
-Requires: libvirt-daemon >= 1.2.4
Requires(post): libcap-tools
%description
Requires: security-containers = %{version}-%{release}
Requires: security-containers-client = %{version}-%{release}
Requires: python
+Requires: python-xml
Requires: boost-test
%description tests
%attr(755,root,root) %{script_dir}/sc_int_tests.py
%attr(755,root,root) %{script_dir}/sc_launch_test.py
%{script_dir}/sc_test_parser.py
-%{_datadir}/security-containers
+%{_datadir}/security-containers/tests
+%attr(755,root,root) %{_datadir}/security-containers/lxc-templates
%{python_sitelib}/sc_integration_tests
/etc/dbus-1/system.d/org.tizen.containers.tests.conf
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex)
-PKG_CHECK_MODULES(SERVER_DEPS REQUIRED json gio-2.0 libsystemd-journal
+PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0 libsystemd-journal
libcap-ng libLogger libSimpleDbus libConfig)
INCLUDE_DIRECTORIES(${COMMON_FOLDER})
## Link libraries ##############################################################
FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex)
-PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED json gio-2.0
+PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0
libsystemd-journal libcap-ng libLogger libSimpleDbus libConfig)
INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
## Subdirectories ##############################################################
SET(SC_TEST_CONFIG_INSTALL_DIR ${SC_DATA_INSTALL_DIR}/tests)
+SET(SC_TEST_LXC_TEMPLATES_INSTALL_DIR ${SC_DATA_INSTALL_DIR}/lxc-templates/tests)
ADD_DEFINITIONS(-DSC_TEST_CONFIG_INSTALL_DIR="${SC_TEST_CONFIG_INSTALL_DIR}")
+ADD_DEFINITIONS(-DSC_TEST_LXC_TEMPLATES_INSTALL_DIR="${SC_TEST_LXC_TEMPLATES_INSTALL_DIR}")
ADD_SUBDIRECTORY(dbus/configs)
ADD_SUBDIRECTORY(server/configs)
ADD_SUBDIRECTORY(utils/configs)
ADD_SUBDIRECTORY(client/configs)
+ADD_SUBDIRECTORY(lxc/templates)
## Install #####################################################################
--- /dev/null
+# 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
+# @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+#
+
+FILE(GLOB LXC_TEMPLATES *.sh)
+
+INSTALL(PROGRAMS ${LXC_TEMPLATES}
+ DESTINATION ${SC_TEST_LXC_TEMPLATES_INSTALL_DIR})
--- /dev/null
+#!/bin/bash
+
+echo UnitTest LXC template, args: $@
+
+options=$(getopt -o p:n: -l rootfs:,path:,name: -- "$@")
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+eval set -- "$options"
+
+while true
+do
+ case "$1" in
+ -p|--path) path=$2; shift 2;;
+ --rootfs) rootfs=$2; shift 2;;
+ -n|--name) name=$2; shift 2;;
+ --) shift 1; break ;;
+ *) break ;;
+ esac
+done
+
+# Prepare container rootfs
+ROOTFS_DIRS="\
+${rootfs}/bin \
+${rootfs}/dev \
+${rootfs}/etc \
+${rootfs}/home \
+${rootfs}/lib \
+${rootfs}/lib64 \
+${rootfs}/proc \
+${rootfs}/root \
+${rootfs}/run \
+${rootfs}/sbin \
+${rootfs}/sys \
+${rootfs}/tmp \
+${rootfs}/usr
+"
+/bin/mkdir ${ROOTFS_DIRS}
+
+# Prepare container configuration file
+> ${path}/config
+cat <<EOF >> ${path}/config
+lxc.utsname = ${name}
+lxc.rootfs = ${rootfs}
+
+lxc.haltsignal = SIGTERM
+
+lxc.pts = 256
+lxc.tty = 0
+
+lxc.mount.auto = proc sys cgroup
+lxc.mount.entry = /bin bin none ro,bind 0 0
+lxc.mount.entry = /etc etc none ro,bind 0 0
+lxc.mount.entry = /lib lib none ro,bind 0 0
+lxc.mount.entry = /sbin sbin none ro,bind 0 0
+lxc.mount.entry = /usr usr none ro,rbind 0 0
+lxc.mount.entry = devtmpfs dev devtmpfs rw,relatime,mode=755 0 0
+EOF
+
+if [ "$(uname -m)" = "x86_64" ]; then
+cat <<EOF >> $path/config
+lxc.mount.entry = /lib64 lib64 none ro,bind 0 0
+EOF
+fi
+
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+
+/**
+ * @file
+ * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
+ * @brief Unit tests of LxcDomain class
+ */
+
+#include "config.hpp"
+#include "ut.hpp"
+
+#include "lxc/domain.hpp"
+#include "lxc/exception.hpp"
+
+#include <thread>
+#include <chrono>
+#include <boost/filesystem.hpp>
+
+namespace {
+
+using namespace security_containers;
+using namespace security_containers::lxc;
+namespace fs = boost::filesystem;
+
+const std::string LXC_PATH = "/tmp/ut-lxc/";
+const std::string DOMAIN_NAME = "ut-domain";
+const std::string TEMPLATE = SC_TEST_LXC_TEMPLATES_INSTALL_DIR "/minimal.sh";
+
+struct Fixture {
+ Fixture()
+ {
+ fs::create_directory(LXC_PATH);
+ cleanup();
+ }
+
+ ~Fixture()
+ {
+ cleanup();
+ fs::remove_all(LXC_PATH);
+ }
+
+ void cleanup()
+ {
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ if (lxc.isDefined()) {
+ if (lxc.isRunning()) {
+ lxc.stop();
+ }
+ lxc.destroy();
+ }
+ }
+};
+
+} // namespace
+
+BOOST_FIXTURE_TEST_SUITE(LxcDomainSuite, Fixture)
+
+BOOST_AUTO_TEST_CASE(ConstructorDestructorTest)
+{
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+}
+
+BOOST_AUTO_TEST_CASE(CreateDestroyTest)
+{
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ BOOST_CHECK(!lxc.isDefined());
+
+ lxc.create(TEMPLATE);
+
+ BOOST_CHECK(lxc.isDefined());
+ BOOST_CHECK_EQUAL(lxc.getConfigItem("lxc.rootfs"), LXC_PATH + DOMAIN_NAME + "/rootfs");
+ BOOST_CHECK_THROW(lxc.getConfigItem("xxx"), LxcException);
+
+ lxc.destroy();
+
+ BOOST_CHECK(!lxc.isDefined());
+}
+
+BOOST_AUTO_TEST_CASE(StartShutdownTest)
+{
+ {
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ lxc.create(TEMPLATE);
+ }
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ BOOST_CHECK_EQUAL("STOPPED", lxc.getState());
+ const char* argv[] = {
+ "/bin/sh",
+ "-c",
+ "trap exit SIGTERM; read",
+ NULL
+ };
+ lxc.start(argv);
+ // wait for bash to be able to trap SIGTERM
+ std::this_thread::sleep_for(std::chrono::milliseconds(200));
+ BOOST_CHECK_EQUAL("RUNNING", lxc.getState());
+ lxc.shutdown(2);
+ BOOST_CHECK_EQUAL("STOPPED", lxc.getState());
+
+ lxc.destroy();
+}
+
+BOOST_AUTO_TEST_CASE(StartStopTest)
+{
+ {
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ lxc.create(TEMPLATE);
+ }
+ LxcDomain lxc(LXC_PATH, DOMAIN_NAME);
+ BOOST_CHECK_EQUAL("STOPPED", lxc.getState());
+ const char* argv[] = {
+ "/bin/sh",
+ NULL
+ };
+ lxc.start(argv);
+ BOOST_CHECK_EQUAL("RUNNING", lxc.getState());
+ BOOST_CHECK_THROW(lxc.shutdown(1), LxcException);
+ BOOST_CHECK_EQUAL("RUNNING", lxc.getState());
+ lxc.stop();
+ BOOST_CHECK_EQUAL("STOPPED", lxc.getState());
+
+ lxc.destroy();
+}
+
+BOOST_AUTO_TEST_SUITE_END()