Implementation of provisioning functions (store declarations) 08/31208/10
authorMateusz Malicki <m.malicki2@samsung.com>
Tue, 2 Dec 2014 13:52:47 +0000 (14:52 +0100)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Tue, 9 Dec 2014 11:51:59 +0000 (03:51 -0800)
[Feature]       Posibility to store provisioning declarations
[Cause]         N/A
[Solution]      Store declarations in config file (using libConfig)
[Verification]  Build, install, run tests

Change-Id: Ie661f1b560adc96798acc7911a2d86eb12fa6616

server/container.cpp
server/container.hpp
server/containers-manager.cpp
server/provisioning-config.hpp [new file with mode: 0644]
tests/unit_tests/server/ut-containers-manager.cpp

index e1377d0..e411798 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "container.hpp"
 #include "base-exception.hpp"
+#include "provisioning-config.hpp"
 
 #include "logger/logger.hpp"
 #include "utils/paths.hpp"
@@ -49,6 +50,18 @@ typedef std::lock_guard<std::recursive_mutex> Lock;
 // TODO: move constants to the config file when default values are implemented there
 const int RECONNECT_RETRIES = 15;
 const int RECONNECT_DELAY = 1 * 1000;
+const std::string CONTAINER_PROVISION_FILE = "provision.conf";
+
+void declareUnit(const std::string& file, ContainerProvisioning::Unit&& unit)
+{
+     // TODO: Add to the dynamic configuration
+    ContainerProvisioning config;
+    if (fs::exists(file)) {
+        config::loadFromFile(file, config);
+    }
+    config.units.push_back(std::move(unit));
+    config::saveToFile(file, config);
+}
 
 } // namespace
 
@@ -71,6 +84,8 @@ Container::Container(const std::string& containersPath,
     }
 
     mAdmin.reset(new ContainerAdmin(containersPath, lxcTemplatePrefix, mConfig));
+    const fs::path baseProvision = fs::path(containersPath) / mAdmin->getId();
+    mProvisionConfig = fs::absolute(CONTAINER_PROVISION_FILE, baseProvision).string();
 }
 
 Container::~Container()
@@ -398,5 +413,36 @@ void Container::proxyCallAsync(const std::string& busName,
     }
 }
 
+void Container::declareFile(const int32_t& type,
+                            const std::string& path,
+                            const int32_t& flags,
+                            const int32_t& mode)
+{
+    ContainerProvisioning::Unit unit;
+    unit.set(std::move(ContainerProvisioning::File({type, path, flags, mode})));
+
+    declareUnit(mProvisionConfig, std::move(unit));
+}
+
+void Container::declareMount(const std::string& source,
+                             const std::string& target,
+                             const std::string& type,
+                             const int64_t& flags,
+                             const std::string& data)
+{
+    ContainerProvisioning::Unit unit;
+    unit.set(std::move(ContainerProvisioning::Mount({source, target, type, flags, data})));
+
+    declareUnit(mProvisionConfig, std::move(unit));
+}
+
+void Container::declareLink(const std::string& source,
+                            const std::string& target)
+{
+    ContainerProvisioning::Unit unit;
+    unit.set(std::move(ContainerProvisioning::Link({source, target})));
+
+    declareUnit(mProvisionConfig, std::move(unit));
+}
 
 } // namespace security_containers
index b0264cb..fe9c317 100644 (file)
@@ -231,6 +231,27 @@ public:
      */
     int getVT() const;
 
+    /**
+     * Declare file, directory or pipe that will be created while container startup
+     */
+    void declareFile(const int32_t& type,
+                     const std::string& path,
+                     const int32_t& flags,
+                     const int32_t& mode);
+    /**
+     * Declare mount that will be created while container startup
+     */
+    void declareMount(const std::string& source,
+                      const std::string& target,
+                      const std::string& type,
+                      const int64_t& flags,
+                      const std::string& data);
+    /**
+     * Declare link that will be created while container startup
+     */
+    void declareLink(const std::string& source,
+                     const std::string& target);
+
 private:
     ContainerConfig mConfig;
     std::vector<boost::regex> mPermittedToSend;
@@ -248,6 +269,7 @@ private:
     DbusStateChangedCallback mDbusStateChangedCallback;
     std::string mDbusAddress;
     std::string mRunMountPoint;
+    std::string mProvisionConfig;
 
     void onNameLostCallback();
     void reconnectHandler();
index c5fb04e..5250b98 100644 (file)
@@ -582,39 +582,63 @@ void ContainersManager::handleGetContainerInfoCall(const std::string& id,
                               rootfsPath.string().c_str()));
 }
 
-void ContainersManager::handleDeclareFileCall(const std::string& /* container */,
-                                              const int32_t& /* type */,
-                                              const std::string& /* path */,
-                                              const int32_t& /* flags */,
-                                              const int32_t& /* mode */,
+void ContainersManager::handleDeclareFileCall(const std::string& container,
+                                              const int32_t& type,
+                                              const std::string& path,
+                                              const int32_t& flags,
+                                              const int32_t& mode,
                                               dbus::MethodResultBuilder::Pointer result)
 {
     LOGI("DeclareFile call");
-    LOGE("Not implemeted method");
-    result->setError(api::ERROR_INTERNAL, "Not implemented");
+    try {
+        mContainers.at(container)->declareFile(type, path, flags, mode);
+        result->setVoid();
+    } catch (const std::out_of_range& ex) {
+        LOGE("No container with id=" << container);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+    } catch (const config::ConfigException& ex) {
+        LOGE("Can't declare file: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, "Internal error");
+    }
 }
 
-void ContainersManager::handleDeclareMountCall(const std::string& /* source */,
-                                               const std::string& /* container */,
-                                               const std::string& /* target */,
-                                               const std::string& /* type */,
-                                               const uint64_t& /* flags */,
-                                               const std::string& /* data */,
+void ContainersManager::handleDeclareMountCall(const std::string& source,
+                                               const std::string& container,
+                                               const std::string& target,
+                                               const std::string& type,
+                                               const uint64_t& flags,
+                                               const std::string& data,
                                                dbus::MethodResultBuilder::Pointer result)
 {
     LOGI("DeclareMount call");
-    LOGE("Not implemeted method");
-    result->setError(api::ERROR_INTERNAL, "Not implemented");
+    try {
+        mContainers.at(container)->declareMount(source, target, type, flags, data);
+        result->setVoid();
+    } catch (const std::out_of_range& ex) {
+        LOGE("No container with id=" << container);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+    } catch (const config::ConfigException& ex) {
+        LOGE("Can't declare mount: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, "Internal error");
+    }
 }
 
-void ContainersManager::handleDeclareLinkCall(const std::string& /* source */,
-                                              const std::string& /* container */,
-                                              const std::string& /* target */,
+void ContainersManager::handleDeclareLinkCall(const std::string& source,
+                                              const std::string& container,
+                                              const std::string& target,
                                               dbus::MethodResultBuilder::Pointer result)
 {
     LOGI("DeclareLink call");
-    LOGE("Not implemeted method");
-    result->setError(api::ERROR_INTERNAL, "Not implemented");
+    try {
+        mContainers.at(container)->declareLink(source, target);
+        result->setVoid();
+    } catch (const std::out_of_range& ex) {
+        LOGE("No container with id=" << container);
+        result->setError(api::ERROR_INVALID_ID, "No such container id");
+    } catch (const config::ConfigException& ex) {
+        LOGE("Can't declare link: " << ex.what());
+        result->setError(api::ERROR_INTERNAL, "Internal error");
+    }
 }
 
 void ContainersManager::handleSetActiveContainerCall(const std::string& id,
diff --git a/server/provisioning-config.hpp b/server/provisioning-config.hpp
new file mode 100644 (file)
index 0000000..e5cf456
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Mateusz Malicki <m.malicki2@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  Mateusz Malicki (m.malicki2@samsung.com)
+ * @brief   Declaration of the class for storing container provisioning configuration
+ */
+
+
+#ifndef SERVER_PROVISIONING_CONFIG_HPP
+#define SERVER_PROVISIONING_CONFIG_HPP
+
+#include "config/fields.hpp"
+#include "config/fields-union.hpp"
+#include <string>
+#include <vector>
+
+
+namespace security_containers {
+
+struct ContainerProvisioning
+{
+
+    struct File
+    {
+        std::int32_t type;
+        std::string path;
+        std::int32_t flags;
+        std::int32_t mode;
+
+        CONFIG_REGISTER
+        (
+            type,
+            path,
+            flags,
+            mode
+        )
+    };
+
+    struct Mount
+    {
+        std::string source;
+        std::string target;
+        std::string type;
+        std::int64_t flags;
+        std::string data;
+
+        CONFIG_REGISTER
+        (
+            source,
+            target,
+            type,
+            flags,
+            data
+        )
+    };
+
+    struct Link
+    {
+        std::string source;
+        std::string target;
+
+        CONFIG_REGISTER
+        (
+            source,
+            target
+        )
+    };
+
+    struct Unit
+    {
+        CONFIG_DECLARE_UNION
+        (
+            File,
+            Mount,
+            Link
+        )
+    };
+
+    std::vector<Unit> units;
+
+    CONFIG_REGISTER
+    (
+        units
+    )
+};
+
+}
+
+#endif // SERVER_PROVISIONING_CONFIG_HPP
index ac4a898..a55400a 100644 (file)
@@ -27,6 +27,9 @@
 #include "ut.hpp"
 
 #include "containers-manager.hpp"
+#include "containers-manager-config.hpp"
+#include "container-config.hpp"
+#include "provisioning-config.hpp"
 #include "container-dbus-definitions.hpp"
 #include "host-dbus-definitions.hpp"
 #include "test-dbus-definitions.hpp"
@@ -37,6 +40,7 @@
 #include "dbus/connection.hpp"
 #include "dbus/exception.hpp"
 #include "utils/glib-loop.hpp"
+#include "config/manager.hpp"
 #include "config/exception.hpp"
 #include "utils/latch.hpp"
 #include "utils/fs.hpp"
@@ -78,6 +82,7 @@ const std::string FILE_CONTENT = "File content\n"
                                  "Line 2\n";
 const std::string NON_EXISTANT_CONTAINER_ID = "NON_EXISTANT_CONTAINER_ID";
 const std::string CONTAINERS_PATH = "/tmp/ut-containers"; // the same as in daemon.conf
+const std::string PROVISON_CONFIG_FILE = "provision.conf";
 
 class DbusAccessory {
 public:
@@ -472,6 +477,26 @@ struct Fixture {
     {}
 };
 
+std::string getProvisionConfigPath(const std::string& container)
+{
+    namespace fs = boost::filesystem;
+    ContainersManagerConfig managerConfig;
+    loadFromFile(TEST_CONFIG_PATH, managerConfig);
+    for (const auto& containersPath : managerConfig.containerConfigs) {
+        ContainerConfig containerConfig;
+        const fs::path configConfigPath = fs::absolute(containersPath,
+                                                       fs::path(TEST_CONFIG_PATH).parent_path());
+
+        loadFromFile(configConfigPath.string(), containerConfig);
+        if (containerConfig.name == container) {
+            const fs::path base = fs::path(managerConfig.containersPath) / fs::path(container);
+            return fs::absolute(PROVISON_CONFIG_FILE, base).string();
+        }
+    }
+    BOOST_FAIL("There is no provision config file for " + container);
+    return std::string();
+}
+
 } // namespace
 
 
@@ -1070,44 +1095,67 @@ BOOST_AUTO_TEST_CASE(CreateDestroyContainerTest)
 
 BOOST_AUTO_TEST_CASE(DeclareFile)
 {
-    //TODO Fill after implementing
     const std::string container = EXPECTED_DBUSES_NO_DBUS.begin()->first;
+    const std::string provisionConfigPath =  getProvisionConfigPath(container);
 
     ContainersManager cm(TEST_CONFIG_PATH);
     DbusAccessory dbus(DbusAccessory::HOST_ID);
-    BOOST_CHECK_EXCEPTION(dbus.callMethodDeclareFile(container, 1, "path", 747, 777),
-                          DbusException,
-                          expectedMessage("Not implemented"));
+    dbus.callMethodDeclareFile(container, 1, "path", 0747, 0777);
+    dbus.callMethodDeclareFile(container, 2, "path", 0747, 0777);
+
+    ContainerProvisioning config;
+    BOOST_REQUIRE_NO_THROW(loadFromFile(provisionConfigPath, config));
+    BOOST_REQUIRE_EQUAL(config.units.size(), 2);
+    BOOST_REQUIRE(config.units[0].is<ContainerProvisioning::File>());
+    BOOST_REQUIRE(config.units[1].is<ContainerProvisioning::File>());
+    const ContainerProvisioning::File& unit = config.units[0].as<ContainerProvisioning::File>();
+    BOOST_CHECK_EQUAL(unit.type, 1);
+    BOOST_CHECK_EQUAL(unit.path, "path");
+    BOOST_CHECK_EQUAL(unit.flags, 0747);
+    BOOST_CHECK_EQUAL(unit.mode, 0777);
 }
 
 BOOST_AUTO_TEST_CASE(DeclareMount)
 {
-    //TODO Fill after implementing
     const std::string container = EXPECTED_DBUSES_NO_DBUS.begin()->first;
+    const std::string provisionConfigPath =  getProvisionConfigPath(container);
 
     ContainersManager cm(TEST_CONFIG_PATH);
     DbusAccessory dbus(DbusAccessory::HOST_ID);
-    BOOST_CHECK_EXCEPTION(dbus.callMethodDeclareMount("/fake/path1",
-                                                           container,
-                                                           "/fake/path2",
-                                                           "tmpfs",
-                                                           77,
-                                                           "fake"),
-                          DbusException,
-                          expectedMessage("Not implemented"));
-
+    dbus.callMethodDeclareMount("/fake/path1", container, "/fake/path2", "tmpfs", 077, "fake");
+    dbus.callMethodDeclareMount("/fake/path2", container, "/fake/path2", "tmpfs", 077, "fake");
+
+    ContainerProvisioning config;
+    BOOST_REQUIRE_NO_THROW(loadFromFile(provisionConfigPath, config));
+    BOOST_REQUIRE_EQUAL(config.units.size(), 2);
+    BOOST_REQUIRE(config.units[0].is<ContainerProvisioning::Mount>());
+    BOOST_REQUIRE(config.units[1].is<ContainerProvisioning::Mount>());
+    const ContainerProvisioning::Mount& unit = config.units[0].as<ContainerProvisioning::Mount>();
+    BOOST_CHECK_EQUAL(unit.source, "/fake/path1");
+    BOOST_CHECK_EQUAL(unit.target, "/fake/path2");
+    BOOST_CHECK_EQUAL(unit.type, "tmpfs");
+    BOOST_CHECK_EQUAL(unit.flags, 077);
+    BOOST_CHECK_EQUAL(unit.data, "fake");
 }
 
 BOOST_AUTO_TEST_CASE(DeclareLink)
 {
-    //TODO Fill after implementing
     const std::string container = EXPECTED_DBUSES_NO_DBUS.begin()->first;
+    const std::string provisionConfigPath =  getProvisionConfigPath(container);
 
     ContainersManager cm(TEST_CONFIG_PATH);
     DbusAccessory dbus(DbusAccessory::HOST_ID);
-    BOOST_CHECK_EXCEPTION(dbus.callMethodDeclareLink("/fake/path1", container, "/fake/path2"),
-                          DbusException,
-                          expectedMessage("Not implemented"));
+    dbus.callMethodDeclareLink("/fake/path1", container, "/fake/path2");
+    dbus.callMethodDeclareLink("/fake/path2", container, "/fake/path2");
+
+    ContainerProvisioning config;
+    BOOST_REQUIRE_NO_THROW(loadFromFile(provisionConfigPath, config));
+    BOOST_REQUIRE_EQUAL(config.units.size(), 2);
+    BOOST_REQUIRE(config.units[0].is<ContainerProvisioning::Link>());
+    BOOST_REQUIRE(config.units[1].is<ContainerProvisioning::Link>());
+    const ContainerProvisioning::Link& unit = config.units[0].as<ContainerProvisioning::Link>();
+    BOOST_CHECK_EQUAL(unit.source, "/fake/path1");
+    BOOST_CHECK_EQUAL(unit.target, "/fake/path2");
 }
 
 BOOST_AUTO_TEST_CASE(LockUnlockContainerTest)