Introduced the Container Manager
authorJan Olszak <j.olszak@samsung.com>
Fri, 7 Mar 2014 16:55:52 +0000 (17:55 +0100)
committerJan Olszak <j.olszak@samsung.com>
Mon, 19 May 2014 11:47:14 +0000 (13:47 +0200)
[Issue#]      PSDAC-64
[Bug]         N/A
[Cause]       N/A
[Solution]    N/A
[Verfication] Build and install, run unit tests.

Change-Id: I8477a67bcb424788e5892e759f057b630c2da3fe

12 files changed:
packaging/security-containers.spec
src/server/include/scs-container-config.hpp
src/server/include/scs-container-manager-config.hpp [new file with mode: 0644]
src/server/include/scs-container-manager.hpp [new file with mode: 0644]
src/server/include/scs-utils.hpp [new file with mode: 0644]
src/server/src/scs-container-manager.cpp [new file with mode: 0644]
src/server/unit_tests/CMakeLists.txt
src/server/unit_tests/config/ut-scs-container-manager/libvirt-config/console.xml [new file with mode: 0644]
src/server/unit_tests/config/ut-scs-container-manager/test-daemon.conf [new file with mode: 0644]
src/server/unit_tests/ut-scs-configuration.cpp
src/server/unit_tests/ut-scs-container-manager.cpp [new file with mode: 0644]
src/server/unit_tests/ut-scs-utils.cpp [new file with mode: 0644]

index aa26851..f385282 100644 (file)
@@ -110,3 +110,5 @@ Unit tests for both: server and client.
 %{script_dir}/sc_test_parser.py
 %{_bindir}/sc_tests_all
 %{_bindir}/sc_test_launch
+%config %attr(644,root,root) /etc/security-containers/config/tests/ut-scs-container-manager/test-daemon.conf
+%config %attr(644,root,root) /etc/security-containers/config/tests/ut-scs-container-manager/libvirt-config/*.xml
index 4cda476..a979162 100644 (file)
 
 namespace security_containers {
 
-struct ContainerConfig : public ConfigurationBase
-{
-    // it's just an example
-    int memory;
-    std::string rootDir;
-
-    CONFIG_REGISTER
-    {
-        CONFIG_VALUE(memory)
-        CONFIG_VALUE(rootDir)
+struct ContainerConfig : public ConfigurationBase {
+    /**
+     * Privilege of the container.
+     * The smaller the value the more important the container
+     */
+    int privilege;
+
+    /**
+     * String id of the container
+     */
+    std::string id;
+
+    CONFIG_REGISTER {
+        CONFIG_VALUE(privilege)
+        CONFIG_VALUE(id)
     }
 };
 
diff --git a/src/server/include/scs-container-manager-config.hpp b/src/server/include/scs-container-manager-config.hpp
new file mode 100644 (file)
index 0000000..ba11a58
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    scs-container-manager-config.hpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Declaration of the class for storing container manager configuration
+ */
+
+
+#ifndef SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_CONFIG_HPP
+#define SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_CONFIG_HPP
+
+#include "scs-configuration.hpp"
+#include <string>
+#include <vector>
+
+namespace security_containers {
+
+const std::string CONTAINER_MANAGER_CONFIG_PATH = "/etc/security-containers/config/.daemon.json";
+
+struct ContainerManagerConfig : public ConfigurationBase {
+    /**
+     * Directory with the libvirt's configuration files
+     */
+    std::string libvirtConfigDir;
+
+    /**
+     * List of containers that we manage.
+     * Appropriate files have to be inside config file
+     */
+    std::vector<std::string> containerIds;
+
+    CONFIG_REGISTER {
+        CONFIG_VALUE(libvirtConfigDir)
+        CONFIG_VALUE(containerIds)
+    }
+};
+
+}
+
+#endif // SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_CONFIG_HPP
diff --git a/src/server/include/scs-container-manager.hpp b/src/server/include/scs-container-manager.hpp
new file mode 100644 (file)
index 0000000..2351fd4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    scs-container-manager.hpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Declaration of the class for managing many containers
+ */
+
+
+#ifndef SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_HPP
+#define SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_HPP
+
+#include "scs-container.hpp"
+#include "scs-container-manager-config.hpp"
+
+#include <string>
+#include <unordered_map>
+
+#include <libvirt/libvirt.h>
+
+namespace security_containers {
+
+class ContainerManager final {
+
+public:
+    ContainerManager(const std::string& configFilePath);
+    ~ContainerManager();
+
+    /**
+     * Switch to this container.
+     * Method blocks until the focus is switched.
+     *
+     * @param containerId id of the container
+     */
+    void focus(const std::string& containerId);
+
+    /**
+     * Start up all the configured containers
+     */
+    void startAll();
+
+    /**
+     * Stop all managed containers
+     */
+    void stopAll();
+
+    /**
+     * @return id of the currently running container
+     */
+    std::string getRunningContainerId();
+
+    /**
+     * @return vector of suspended container ids
+     */
+    std::vector<std::string> getSuspendedContainerIds();
+
+private:
+    ContainerManagerConfig mConfig;
+    virConnectPtr mVir = NULL; // pointer to the connection with libvirt
+    std::unordered_map<std::string, Container> mContainers; // map of containers, id is the key
+
+    void connect();
+    void disconnect();
+};
+}
+#endif // SECURITY_CONTAINERS_SERVER_CONTAINER_MANAGER_HPP
diff --git a/src/server/include/scs-utils.hpp b/src/server/include/scs-utils.hpp
new file mode 100644 (file)
index 0000000..006af2e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    scs-utils.hpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Utility function declaration
+ */
+
+
+#include <string>
+#include <vector>
+
+
+namespace security_containers {
+
+template <class ...Paths> std::string createFilePath(const Paths& ... paths)
+{
+    std::vector<std::string> pathVec = {paths...};
+    std::string retPath = "";
+
+    if (pathVec.empty()) {
+        return retPath;
+    }
+
+    for (std::string& p : pathVec) {
+        // Repeat until retPath is not empty
+        if (retPath.empty() || p.empty()) {
+            retPath += p;
+            continue;
+        }
+
+        // We need a slash
+        if (retPath.back() != '/' && p.front() != '/' && p.front() != '.') {
+            retPath += "/" + p;
+            continue;
+        }
+
+        // Too many slashes
+        if (retPath.back() == '/' && p.front() == '/') {
+            retPath += p.substr(1);
+            continue;
+        }
+
+        retPath += p;
+    }
+
+    return retPath;
+}
+
+} // namespace security_containers
\ No newline at end of file
diff --git a/src/server/src/scs-container-manager.cpp b/src/server/src/scs-container-manager.cpp
new file mode 100644 (file)
index 0000000..1e05fcf
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    scs-container-manager.cpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Definition of the class for managing containers
+ */
+
+#include "scs-container-manager.hpp"
+#include "scs-container.hpp"
+#include "scs-exception.hpp"
+#include "scs-log.hpp"
+#include "scs-utils.hpp"
+
+#include <assert.h>
+#include <string>
+#include <fstream>
+#include <streambuf>
+
+namespace security_containers {
+
+ContainerManager::ContainerManager(const std::string& configFilePath)
+{
+    mConfig.parseFile(configFilePath);
+    connect();
+    for (auto& containerId : mConfig.containerIds) {
+        std::string libvirtConfigPath = createFilePath(mConfig.libvirtConfigDir, containerId, ".xml");
+        std::ifstream t(libvirtConfigPath);
+        std::string libvirtConfig((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
+        LOGT("Creating Container " << libvirtConfigPath);
+        mContainers.emplace(containerId, libvirtConfig);
+    }
+}
+
+
+ContainerManager::~ContainerManager()
+{
+    try {
+        stopAll();
+    } catch (ServerException& e) {
+        LOGE("Failed to stop all of the containers");
+    }
+    disconnect();
+}
+
+
+void ContainerManager::focus(const std::string& containerId)
+{
+    for (auto& container : mContainers) {
+        container.second.suspend();
+    }
+    mContainers.at(containerId).resume();
+}
+
+
+void ContainerManager::startAll()
+{
+    for (auto& container : mContainers) {
+        container.second.start();
+    }
+}
+
+
+void ContainerManager::stopAll()
+{
+    for (auto& container : mContainers) {
+        container.second.stop();
+    }
+}
+
+
+std::string ContainerManager::getRunningContainerId()
+{
+    for (auto& container : mContainers) {
+        if (container.second.isRunning()) {
+            return container.first;
+        }
+    }
+    return "";
+}
+
+
+std::vector<std::string> ContainerManager::getSuspendedContainerIds()
+{
+    std::vector<std::string> retContainerIds;
+    for (auto& container : mContainers) {
+        if (container.second.isPaused()) {
+            retContainerIds.push_back(container.first);
+        }
+    }
+    return retContainerIds;
+}
+
+
+void ContainerManager::connect()
+{
+    assert(mVir == NULL);
+
+    mVir = virConnectOpen("lxc://");
+    if (mVir == NULL) {
+        LOGE("Failed to open connection to lxc://");
+        throw ConnectionException();
+    }
+}
+
+
+void ContainerManager::disconnect()
+{
+    if (mVir == NULL) {
+        return;
+    }
+
+    if (virConnectClose(mVir) < 0) {
+        LOGE("Error during unconnecting from libvirt");
+    };
+    mVir = NULL;
+}
+
+
+} // namespace security_containers
\ No newline at end of file
index 54ace7c..9e8a53c 100644 (file)
@@ -20,6 +20,7 @@
 MESSAGE ("Generating makefile for the Server unit tests...")
 FILE(GLOB_RECURSE project_SRCS *.cpp)
 FILE(GLOB src_SRCS ${SERVER_FOLDER}/src/scs-container.cpp
+                   ${SERVER_FOLDER}/src/scs-container-manager.cpp
                    ${SERVER_FOLDER}/src/scs-configuration.cpp)
 
 MESSAGE("Files: " ${project_SRCS} ${src_SRCS})
@@ -39,4 +40,10 @@ INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
 TARGET_LINK_LIBRARIES(${UT_SERVER_CODENAME} ${UT_SERVER_DEPS_LIBRARIES} ${Boost_LIBRARIES})
 
 ## Install #####################################################################
-INSTALL(TARGETS ${UT_SERVER_CODENAME} DESTINATION bin)
\ No newline at end of file
+INSTALL(TARGETS ${UT_SERVER_CODENAME} DESTINATION bin)
+
+INSTALL(FILES       ${SERVER_FOLDER}/unit_tests/config/ut-scs-container-manager/test-daemon.conf
+        DESTINATION /etc/security-containers/config/tests/ut-scs-container-manager/)
+
+INSTALL(FILES       ${SERVER_FOLDER}/unit_tests/config/ut-scs-container-manager/libvirt-config/console.xml
+        DESTINATION /etc/security-containers/config/tests/ut-scs-container-manager/libvirt-config/)
diff --git a/src/server/unit_tests/config/ut-scs-container-manager/libvirt-config/console.xml b/src/server/unit_tests/config/ut-scs-container-manager/libvirt-config/console.xml
new file mode 100644 (file)
index 0000000..a301f33
--- /dev/null
@@ -0,0 +1,11 @@
+<domain type="lxc">
+    <name>console</name>
+    <memory>102400</memory>
+    <os>
+        <type>exe</type>
+        <init>/bin/sh</init>
+    </os>
+    <devices>
+        <console type="pty"/>
+    </devices>
+</domain>
diff --git a/src/server/unit_tests/config/ut-scs-container-manager/test-daemon.conf b/src/server/unit_tests/config/ut-scs-container-manager/test-daemon.conf
new file mode 100644 (file)
index 0000000..7233b91
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    "libvirtConfigDir" : "/etc/security-containers/config/tests/ut-scs-container-manager/libvirt-config",
+    "containerIds" : ["console", "console1"]
+}
index d646594..661a17e 100644 (file)
@@ -174,15 +174,9 @@ BOOST_AUTO_TEST_CASE(ToStringTest)
 {
     TestConfig testConfig;
     BOOST_REQUIRE_NO_THROW(testConfig.parseStr(json_test_string));
-
-    std::cout << "Input:" << std::endl << json_test_string << std::endl;
-
-    std::string out;
-    BOOST_REQUIRE_NO_THROW(out = testConfig.toString());
-    std::cout << std::endl << "Output:" << std::endl << out << std::endl;
+    BOOST_REQUIRE_NO_THROW(testConfig.toString());
 
     // parse output again and check if both objects match
-    std::cout << "Validating output..." << std::endl;
     TestConfig outputConfig;
     BOOST_REQUIRE_NO_THROW(outputConfig.parseStr(json_test_string));
     BOOST_CHECK(outputConfig == testConfig);
diff --git a/src/server/unit_tests/ut-scs-container-manager.cpp b/src/server/unit_tests/ut-scs-container-manager.cpp
new file mode 100644 (file)
index 0000000..b36f935
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    ut-scs-container.cpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Unit tests of the Container class
+ */
+
+#include "ut.hpp"
+#include "scs-container-manager.hpp"
+#include "scs-exception.hpp"
+
+#include <memory>
+#include <string>
+
+
+BOOST_AUTO_TEST_SUITE(ContainerManagerSuite)
+
+using namespace security_containers;
+
+const std::string daemonConfigPath = "/etc/security-containers/config/tests/ut-scs-container-manager/test-daemon.conf";
+
+
+BOOST_AUTO_TEST_CASE(ConstructorTest)
+{
+    BOOST_REQUIRE_NO_THROW(ContainerManager cm(daemonConfigPath););
+}
+
+BOOST_AUTO_TEST_CASE(DestructorTest)
+{
+    std::unique_ptr<ContainerManager> cm(new ContainerManager(daemonConfigPath));
+    BOOST_REQUIRE_NO_THROW(cm.reset());
+}
+
+BOOST_AUTO_TEST_CASE(StartAllTest)
+{
+    ContainerManager cm(daemonConfigPath);
+    BOOST_REQUIRE_NO_THROW(cm.startAll());
+    BOOST_CHECK(!cm.getRunningContainerId().empty());
+}
+
+BOOST_AUTO_TEST_CASE(StopAllTest)
+{
+    ContainerManager cm(daemonConfigPath);
+    BOOST_REQUIRE_NO_THROW(cm.startAll());
+    BOOST_REQUIRE_NO_THROW(cm.stopAll());
+    BOOST_CHECK(cm.getRunningContainerId().empty());
+
+}
+
+BOOST_AUTO_TEST_CASE(FocusTest)
+{
+    ContainerManager cm(daemonConfigPath);
+    BOOST_REQUIRE_NO_THROW(cm.startAll());
+    BOOST_REQUIRE_NO_THROW(cm.focus("console"));
+    BOOST_CHECK(!cm.getSuspendedContainerIds().empty());
+    BOOST_TEST_MESSAGE("Suspended");
+    for (auto& id : cm.getSuspendedContainerIds()) {
+        BOOST_TEST_MESSAGE(id);
+    }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/server/unit_tests/ut-scs-utils.cpp b/src/server/unit_tests/ut-scs-utils.cpp
new file mode 100644 (file)
index 0000000..7c6f3e9
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Bumjin Im <bj.im@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    ut-scs-utils.cpp
+ * @author  Jan Olszak (j.olszak@samsung.com)
+ * @brief   Unit tests of utils
+ */
+
+#include "ut.hpp"
+#include "scs-utils.hpp"
+#include "scs-exception.hpp"
+
+#include <memory>
+
+BOOST_AUTO_TEST_SUITE(UtilsSuite)
+
+using namespace security_containers;
+
+BOOST_AUTO_TEST_CASE(CreateFilePathTest)
+{
+    BOOST_CHECK_EQUAL("", createFilePath());
+
+    BOOST_CHECK_EQUAL("a", createFilePath("a"));
+    BOOST_CHECK_EQUAL("/", createFilePath("/"));
+
+    BOOST_CHECK_EQUAL("", createFilePath("", ""));
+    BOOST_CHECK_EQUAL("a", createFilePath("a", ""));
+    BOOST_CHECK_EQUAL("b", createFilePath("", "b"));
+    BOOST_CHECK_EQUAL("/", createFilePath("", "/"));
+    BOOST_CHECK_EQUAL("/", createFilePath("/", ""));
+    BOOST_CHECK_EQUAL("/", createFilePath("/", "/"));
+
+    BOOST_CHECK_EQUAL("a/b", createFilePath("a", "b"));
+    BOOST_CHECK_EQUAL("a/b", createFilePath("a/", "b"));
+    BOOST_CHECK_EQUAL("a/b", createFilePath("a", "/b"));
+    BOOST_CHECK_EQUAL("a/b", createFilePath("a/", "/b"));
+
+    BOOST_CHECK_EQUAL("a/b.txt",  createFilePath("a", "b", ".txt"));
+    BOOST_CHECK_EQUAL("a/b.txt",  createFilePath("a/", "b", ".txt"));
+    BOOST_CHECK_EQUAL("a/b.txt",  createFilePath("a", "/b", ".txt"));
+    BOOST_CHECK_EQUAL("a/b/.txt", createFilePath("a", "/b", "/.txt"));
+    BOOST_CHECK_EQUAL("a/b/.txt", createFilePath("a", "/b/", "/.txt"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()