lxcpp: provisioning implementation (part 1) 97/49597/11
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Thu, 15 Oct 2015 09:42:52 +0000 (11:42 +0200)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 20 Oct 2015 14:50:42 +0000 (16:50 +0200)
[Feature]       Provisioning implementation for lxcpp (declare, list, remove)
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, install, run tests

Change-Id: I3823587de023a9f1a9e34208ae9e188521dbe3b1

12 files changed:
libs/lxcpp/commands/command.hpp
libs/lxcpp/commands/provision.cpp [new file with mode: 0644]
libs/lxcpp/commands/provision.hpp [new file with mode: 0644]
libs/lxcpp/container-config.hpp
libs/lxcpp/container-impl.cpp
libs/lxcpp/container-impl.hpp
libs/lxcpp/container.hpp
libs/lxcpp/exception.hpp
libs/lxcpp/guard/guard.cpp
libs/lxcpp/provision-config.cpp [new file with mode: 0644]
libs/lxcpp/provision-config.hpp [new file with mode: 0644]
tests/unit_tests/lxcpp/ut-provisioning.cpp [new file with mode: 0644]

index cd301ee..a1ba473 100644 (file)
@@ -28,9 +28,13 @@ namespace lxcpp {
 
 class Command {
 public:
+    // do sth [mandatory]
     virtual void execute() = 0;
+
+    // roll-back execute() action [optional]
+    virtual void revert() {}
 };
 
 } // namespace lxcpp
 
-#endif // LXCPP_COMMANDS_COMMAND_HPP
\ No newline at end of file
+#endif // LXCPP_COMMANDS_COMMAND_HPP
diff --git a/libs/lxcpp/commands/provision.cpp b/libs/lxcpp/commands/provision.cpp
new file mode 100644 (file)
index 0000000..ba97393
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Add new provisioned file/dir/link/mount command
+ */
+
+#include "lxcpp/commands/provision.hpp"
+#include "lxcpp/container.hpp"
+#include "lxcpp/provision-config.hpp"
+
+namespace lxcpp {
+
+void Provisions::execute()
+{
+    for(const auto & file : mConfig.mProvisions.files) {
+        ProvisionFile(mConfig, file).execute();
+    }
+
+    for(const auto & mount : mConfig.mProvisions.mounts) {
+        ProvisionMount(mConfig, mount).execute();
+    }
+
+    for(const auto & link : mConfig.mProvisions.links) {
+        ProvisionLink(mConfig, link).execute();
+    }
+}
+void Provisions::revert()
+{
+    for(const auto & file : mConfig.mProvisions.files) {
+        ProvisionFile(mConfig, file).revert();
+    }
+
+    for(const auto & mount : mConfig.mProvisions.mounts) {
+        ProvisionMount(mConfig, mount).revert();
+    }
+
+    for(const auto & link : mConfig.mProvisions.links) {
+        ProvisionLink(mConfig, link).revert();
+    }
+}
+
+
+void ProvisionFile::execute()
+{
+    // MJK TODO: add file
+}
+void ProvisionFile::revert()
+{
+    // MJK TODO: remove file from container
+}
+
+
+void ProvisionMount::execute()
+{
+    // MJK TODO: add mount
+}
+void ProvisionMount::revert()
+{
+    // MJK TODO: remove mount from container
+}
+
+
+void ProvisionLink::execute()
+{
+    // MJK TODO: add link
+}
+void ProvisionLink::revert()
+{
+    // MJK TODO: remove link from container
+}
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/commands/provision.hpp b/libs/lxcpp/commands/provision.hpp
new file mode 100644 (file)
index 0000000..0b7411a
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Add new provisioned file/dir/link/mount command
+ */
+
+#ifndef LXCPP_COMMAND_PROVISION_HPP
+#define LXCPP_COMMAND_PROVISION_HPP
+
+#include "lxcpp/commands/command.hpp"
+#include "lxcpp/container-config.hpp"
+#include "lxcpp/provision-config.hpp"
+
+#include <sys/types.h>
+
+namespace lxcpp {
+
+class Provisions final: Command {
+public:
+   /**
+    * Runs call in the container's context
+    *
+    * Add/remove all file/fifo/dir/mount/link provisions to/from the container
+    */
+    Provisions(ContainerConfig &config) : mConfig(config)
+    {
+    }
+
+    void execute();
+    void revert();
+
+private:
+    ContainerConfig& mConfig;
+};
+
+
+class ProvisionFile final: Command {
+public:
+   /**
+    * Runs call in the container's context
+    *
+    * Add/remove new file/fifo/dir provision to/from the container
+    */
+    ProvisionFile(ContainerConfig &config, const provision::File &file) :
+        mConfig(config), mFile(file)
+    {
+    }
+
+    void execute();
+    void revert();
+
+private:
+    ContainerConfig& mConfig;
+    const provision::File& mFile;
+};
+
+class ProvisionMount final: Command {
+public:
+   /**
+    * Runs call in the container's context
+    *
+    * Add/remove new mount provision to/from the container
+    */
+    ProvisionMount(ContainerConfig &config, const provision::Mount &mount) :
+        mConfig(config), mMount(mount)
+    {
+    }
+
+    void execute();
+    void revert();
+
+private:
+    ContainerConfig& mConfig;
+    const provision::Mount& mMount;
+};
+
+class ProvisionLink final: Command {
+public:
+   /**
+    * Runs call in the container's context
+    *
+    * Add/remove link provision to/from the container
+    */
+    ProvisionLink(ContainerConfig &config, const provision::Link &link) :
+        mConfig(config), mLink(link)
+    {
+    }
+
+    void execute();
+    void revert();
+
+private:
+    ContainerConfig& mConfig;
+    const provision::Link& mLink;
+};
+
+} // namespace lxcpp
+
+#endif // LXCPP_COMMAND_PROVISION_HPP
index 4fbf86d..1a487cf 100644 (file)
@@ -27,6 +27,7 @@
 #include "lxcpp/logger-config.hpp"
 #include "lxcpp/network-config.hpp"
 #include "lxcpp/terminal-config.hpp"
+#include "lxcpp/provision-config.hpp"
 
 #include <config/config.hpp>
 #include <config/fields.hpp>
@@ -117,6 +118,14 @@ struct ContainerConfig {
      */
     int mNamespaces;
 
+    /**
+     * available files/dirs/mounts/links
+     *
+     * Set: by container provision manipulation methods
+     * Get: getFiles(), getMounts(), getLinks()
+     */
+    ProvisionConfig mProvisions;
+
     ContainerConfig() : mGuardPid(-1), mInitPid(-1), mNamespaces(0) {}
 
     CONFIG_REGISTER
@@ -128,7 +137,8 @@ struct ContainerConfig {
         mInit,
         mLogger,
         mTerminals,
-        mNamespaces
+        mNamespaces,
+        mProvisions
     )
 };
 
index e19012c..29d6cb0 100644 (file)
@@ -31,6 +31,7 @@
 #include "lxcpp/commands/start.hpp"
 #include "lxcpp/commands/stop.hpp"
 #include "lxcpp/commands/prep-host-terminal.hpp"
+#include "lxcpp/commands/provision.hpp"
 
 #include "logger/logger.hpp"
 #include "utils/exception.hpp"
@@ -170,7 +171,7 @@ void ContainerImpl::start()
 
 void ContainerImpl::stop()
 {
-    // TODO: things to do when shuttting down the container:
+    // TODO: things to do when shutting down the container:
     // - close PTY master FDs from the config so we won't keep PTYs open
 
     Stop stop(mConfig);
@@ -215,6 +216,12 @@ void ContainerImpl::console()
     console.execute();
 }
 
+bool ContainerImpl::isRunning() const
+{
+    // TODO: race condition may occur, sync needed
+    return getInitPid() != -1;
+}
+
 void ContainerImpl::addInterfaceConfig(const std::string& hostif,
                                        const std::string& zoneif,
                                        InterfaceType type,
@@ -305,4 +312,93 @@ void ContainerImpl::delInetAddr(const std::string& ifname, const InetAddr& addr)
     ni.delInetAddr(addr);
 }
 
+void ContainerImpl::declareFile(const provision::File::Type type,
+                                const std::string& path,
+                                const int32_t flags,
+                                const int32_t mode)
+{
+    provision::File newFile({type, path, flags, mode});
+    mConfig.mProvisions.addFile(newFile);
+    // TODO: update guard config
+
+    if (isRunning()) {
+        ProvisionFile fileCmd(mConfig, newFile);
+        fileCmd.execute();
+    }
+}
+
+const FileVector& ContainerImpl::getFiles() const
+{
+    return mConfig.mProvisions.getFiles();
+}
+
+void ContainerImpl::removeFile(const provision::File& item)
+{
+    mConfig.mProvisions.removeFile(item);
+
+    if (isRunning()) {
+        ProvisionFile fileCmd(mConfig, item);
+        fileCmd.revert();
+    }
+}
+
+void ContainerImpl::declareMount(const std::string& source,
+                                 const std::string& target,
+                                 const std::string& type,
+                                 const int64_t flags,
+                                 const std::string& data)
+{
+    provision::Mount newMount({source, target, type, flags, data});
+    mConfig.mProvisions.addMount(newMount);
+    // TODO: update guard config
+
+    if (isRunning()) {
+        ProvisionMount mountCmd(mConfig, newMount);
+        mountCmd.execute();
+    }
+}
+
+const MountVector& ContainerImpl::getMounts() const
+{
+    return mConfig.mProvisions.getMounts();
+}
+
+void ContainerImpl::removeMount(const provision::Mount& item)
+{
+    mConfig.mProvisions.removeMount(item);
+
+    if (isRunning()) {
+        ProvisionMount mountCmd(mConfig, item);
+        mountCmd.revert();
+    }
+}
+
+void ContainerImpl::declareLink(const std::string& source,
+                                const std::string& target)
+{
+    provision::Link newLink({source, target});
+    mConfig.mProvisions.addLink(newLink);
+    // TODO: update guard config
+
+    if (isRunning()) {
+        ProvisionLink linkCmd(mConfig, newLink);
+        linkCmd.execute();
+    }
+}
+
+const LinkVector& ContainerImpl::getLinks() const
+{
+    return mConfig.mProvisions.getLinks();
+}
+
+void ContainerImpl::removeLink(const provision::Link& item)
+{
+    mConfig.mProvisions.removeLink(item);
+
+    if (isRunning()) {
+        ProvisionLink linkCmd(mConfig, item);
+        linkCmd.revert();
+    }
+}
+
 } // namespace lxcpp
index d3db492..f1cba58 100644 (file)
@@ -69,6 +69,7 @@ public:
     void attach(const std::vector<std::string>& argv,
                 const std::string& cwdInContainer);
     void console();
+    bool isRunning() const;
 
     // Network interfaces setup/config
     /**
@@ -96,6 +97,27 @@ public:
     void addInetAddr(const std::string& ifname, const InetAddr& addr);
     void delInetAddr(const std::string& ifname, const InetAddr& addr);
 
+    // Provisioning
+    void declareFile(const provision::File::Type type,
+                     const std::string& path,
+                     const int32_t flags,
+                     const int32_t mode);
+    const FileVector& getFiles() const;
+    void removeFile(const provision::File& item);
+
+    void declareMount(const std::string& source,
+                      const std::string& target,
+                      const std::string& type,
+                      const int64_t flags,
+                      const std::string& data);
+    const MountVector& getMounts() const;
+    void removeMount(const provision::Mount& item);
+
+    void declareLink(const std::string& source,
+                     const std::string& target);
+    const LinkVector& getLinks() const;
+    void removeLink(const provision::Link& item);
+
 private:
     ContainerConfig mConfig;
 };
index 096463b..2d0e696 100644 (file)
@@ -25,6 +25,7 @@
 #define LXCPP_CONTAINER_HPP
 
 #include "lxcpp/network-config.hpp"
+#include "lxcpp/provision-config.hpp"
 #include "lxcpp/logger-config.hpp"
 
 #include <sys/types.h>
@@ -78,6 +79,7 @@ public:
     virtual void attach(const std::vector<std::string>& argv,
                         const std::string& cwdInContainer) = 0;
     virtual void console() = 0;
+    virtual bool isRunning() const = 0;
 
     // Network interfaces setup/config
     virtual void addInterfaceConfig(const std::string& hostif,
@@ -100,6 +102,27 @@ public:
     virtual void setDown(const std::string& ifname) = 0;
     virtual void addInetAddr(const std::string& ifname, const InetAddr& addr) = 0;
     virtual void delInetAddr(const std::string& ifname, const InetAddr& addr) = 0;
+
+    // Provisioning
+    virtual void declareFile(const provision::File::Type type,
+                             const std::string& path,
+                             const int32_t flags,
+                             const int32_t mode) = 0;
+    virtual const FileVector& getFiles() const = 0;
+    virtual void removeFile(const provision::File& item) = 0;
+
+    virtual void declareMount(const std::string& source,
+                              const std::string& target,
+                              const std::string& type,
+                              const int64_t flags,
+                              const std::string& data) = 0;
+    virtual const MountVector& getMounts() const = 0;
+    virtual void removeMount(const provision::Mount& item) = 0;
+
+    virtual void declareLink(const std::string& source,
+                             const std::string& target) = 0;
+    virtual const LinkVector& getLinks() const = 0;
+    virtual void removeLink(const provision::Link& item) = 0;
 };
 
 } // namespace lxcpp
index 387e2eb..37fec5a 100644 (file)
@@ -96,6 +96,11 @@ struct ConfigureException: public Exception {
         : Exception(message) {}
 };
 
+struct ProvisionException: public Exception {
+    explicit ProvisionException(const std::string& message = "Provision error")
+        : Exception(message) {}
+};
+
 } // namespace lxcpp
 
 #endif // LXCPP_EXCEPTION_HPP
index 4f56771..f96fe7a 100644 (file)
@@ -25,6 +25,7 @@
 #include "lxcpp/guard/guard.hpp"
 #include "lxcpp/process.hpp"
 #include "lxcpp/commands/prep-guest-terminal.hpp"
+#include "lxcpp/commands/provision.hpp"
 
 #include "config/manager.hpp"
 #include "logger/logger.hpp"
@@ -42,6 +43,9 @@ int startContainer(void* data)
 
     // TODO: container preparation part 2
 
+    Provisions provisions(config);
+    provisions.execute();
+
     PrepGuestTerminal terminals(config.mTerminals);
     terminals.execute();
 
@@ -96,6 +100,11 @@ int Guard::execute()
 
     int status = lxcpp::waitpid(initPid);
     LOGD("Init exited with status: " << status);
+
+    // TODO: cleanup after child exits
+    Provisions provisions(mConfig);
+    provisions.revert();
+
     return status;
 }
 
diff --git a/libs/lxcpp/provision-config.cpp b/libs/lxcpp/provision-config.cpp
new file mode 100644 (file)
index 0000000..459ba70
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Provisioning configuration
+ */
+
+#include <vector>
+#include <string>
+#include "lxcpp/container-config.hpp"
+
+using namespace lxcpp;
+using namespace provision;
+
+void ProvisionConfig::addFile(const File& newFile)
+{
+    auto it = std::find(files.begin(), files.end(), newFile);
+    if (it != files.end()) {
+        const std::string msg =
+            "Can't add file. Provision already exists: " + newFile.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    files.push_back(newFile);
+}
+
+const FileVector& ProvisionConfig::getFiles() const
+{
+    return files;
+}
+
+void ProvisionConfig::removeFile(const File& item)
+{
+    const auto it = std::find(files.begin(), files.end(), item);
+    if (it == files.end()) {
+        const std::string msg = "Can't find provision: " + item.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    files.erase(it);
+}
+
+
+void ProvisionConfig::addMount(const Mount& newMount)
+{
+    auto it = std::find(mounts.begin(), mounts.end(), newMount);
+    if (it != mounts.end()) {
+        const std::string msg =
+            "Can't add mount. Provision already exists: " + newMount.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    mounts.push_back(newMount);
+}
+
+const MountVector& ProvisionConfig::getMounts() const
+{
+    return mounts;
+}
+
+void ProvisionConfig::removeMount(const Mount& item)
+{
+    const auto it = std::find(mounts.begin(), mounts.end(), item);
+    if (it == mounts.end()) {
+        const std::string msg = "Can't find provision: " + item.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    mounts.erase(it);
+}
+
+
+void ProvisionConfig::addLink(const Link& newLink)
+{
+    auto it = std::find(links.begin(), links.end(), newLink);
+    if (it != links.end()) {
+        const std::string msg =
+            "Can't add link. Provision already exists: " + newLink.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    links.push_back(newLink);
+}
+
+const LinkVector& ProvisionConfig::getLinks() const
+{
+    return links;
+}
+
+void ProvisionConfig::removeLink(const Link& item)
+{
+    const auto it = std::find(links.begin(), links.end(), item);
+    if (it == links.end()) {
+        const std::string msg = "Can't find provision: " + item.getId();
+        LOGE(msg);
+        throw ProvisionException(msg);
+    }
+    links.erase(it);
+}
diff --git a/libs/lxcpp/provision-config.hpp b/libs/lxcpp/provision-config.hpp
new file mode 100644 (file)
index 0000000..fb9cbc4
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Provisioning configuration
+ */
+
+#ifndef LXCPP_PROVISION_CONFIG_HPP
+#define LXCPP_PROVISION_CONFIG_HPP
+
+#include "config/config.hpp"
+#include "config/fields.hpp"
+#include "config/fields-union.hpp"
+
+#include <vector>
+#include <string>
+#include <string.h>
+
+namespace lxcpp {
+namespace provision {
+
+typedef std::string ProvisionID;
+
+/**
+ * Provision configuration items
+ */
+struct File
+{
+    enum class Type : int
+    {
+        DIRECTORY,
+        FIFO,
+        REGULAR
+    };
+
+    ProvisionID getId() const
+    {
+        return "file " +
+               path + " " +
+               std::to_string(static_cast<int>(type)) + " " +
+               std::to_string(flags) + " " +
+               std::to_string(mode);
+    }
+
+    Type type;
+    std::string path;
+    std::int32_t flags;
+    std::int32_t mode;
+
+    CONFIG_REGISTER
+    (
+        type,
+        path,
+        flags,
+        mode
+    )
+
+    bool operator==(const File& m) const
+    {
+        return ((m.type == type) && (m.path == path) &&
+                (m.flags == flags) && (m.mode == mode));
+    }
+};
+
+struct Mount
+{
+    ProvisionID getId() const
+    {
+        return "mount " +
+               source + " " +
+               target + " " +
+               type + " " +
+               std::to_string(flags) + " " +
+               data;
+    }
+
+    std::string source;
+    std::string target;
+    std::string type;
+    std::int64_t flags;
+    std::string data;
+
+    CONFIG_REGISTER
+    (
+        source,
+        target,
+        type,
+        flags,
+        data
+    )
+
+    bool operator==(const Mount& m) const
+    {
+        return ((m.source == source) && (m.target == target) && (m.type == type) &&
+                (m.flags == flags) && (m.data == data));
+    }
+};
+
+struct Link
+{
+    ProvisionID getId() const
+    {
+        return "link " + source + " " + target;
+    }
+
+    std::string source;
+    std::string target;
+
+    CONFIG_REGISTER
+    (
+        source,
+        target
+    )
+
+    bool operator==(const Link& m) const
+    {
+        return ((m.source == source) && (m.target == target));
+    }
+};
+} // namespace provision
+
+typedef std::vector<provision::File>   FileVector;
+typedef std::vector<provision::Mount>  MountVector;
+typedef std::vector<provision::Link>   LinkVector;
+
+struct ProvisionConfig
+{
+    FileVector files;
+    MountVector mounts;
+    LinkVector links;
+
+    void addFile(const provision::File& newFile);
+    const FileVector& getFiles() const;
+    void removeFile(const provision::File& item);
+
+    void addMount(const provision::Mount& newMount);
+    const MountVector& getMounts() const;
+    void removeMount(const provision::Mount& item);
+
+    void addLink(const provision::Link& newLink);
+    const LinkVector& getLinks() const;
+    void removeLink(const provision::Link& item);
+
+    CONFIG_REGISTER
+    (
+        files,
+        mounts,
+        links
+    )
+};
+
+} // namespace lxcpp
+
+#endif // LXCPP_PROVISION_CONFIG_HPP
diff --git a/tests/unit_tests/lxcpp/ut-provisioning.cpp b/tests/unit_tests/lxcpp/ut-provisioning.cpp
new file mode 100644 (file)
index 0000000..d2a535c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License version 2.1 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/**
+ * @file
+ * @author  Maciej Karpiuk (m.karpiuk2@samsung.com)
+ * @brief   Unit tests of lxcpp provisioning
+ */
+
+#include "config.hpp"
+#include "config/manager.hpp"
+#include "lxcpp/lxcpp.hpp"
+#include "lxcpp/container.hpp"
+#include "lxcpp/container-config.hpp"
+#include "lxcpp/provision-config.hpp"
+#include "ut.hpp"
+#include "utils/scoped-dir.hpp"
+#include <iostream>
+
+namespace {
+
+using namespace lxcpp;
+using namespace config;
+using namespace provision;
+
+const std::string TEST_DIR            = "/tmp/ut-provisioning";
+const std::string ROOT_DIR            = TEST_DIR + "/root";
+
+struct Fixture {
+    Fixture() : mTestPath(ROOT_DIR) {
+        container = std::unique_ptr<Container>(createContainer("ProvisioningTester", ROOT_DIR));
+    }
+    ~Fixture() {}
+
+    std::unique_ptr<Container> container;
+    utils::ScopedDir mTestPath;
+};
+
+} // namespace
+
+
+BOOST_FIXTURE_TEST_SUITE(LxcppProvisioningSuite, Fixture)
+
+BOOST_AUTO_TEST_CASE(ListProvisionsEmptyContainer)
+{
+    BOOST_REQUIRE(container->getFiles().size() == 0);
+    BOOST_REQUIRE(container->getMounts().size() == 0);
+    BOOST_REQUIRE(container->getLinks().size() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(AddDeclareFile)
+{
+    container->declareFile(File::Type::FIFO, "path", 0747, 0777);
+    container->declareFile(File::Type::REGULAR, "path", 0747, 0777);
+
+    std::vector<File> fileList = container->getFiles();
+    BOOST_REQUIRE_EQUAL(fileList.size(), 2);
+
+    BOOST_REQUIRE(fileList[0].type == File::Type::FIFO);
+    BOOST_REQUIRE(fileList[0].path == "path");
+    BOOST_REQUIRE(fileList[0].flags == 0747);
+    BOOST_REQUIRE(fileList[0].mode == 0777);
+    BOOST_REQUIRE(fileList[1].type == File::Type::REGULAR);
+
+    BOOST_REQUIRE_NO_THROW(container->removeFile(fileList[0]));
+    BOOST_REQUIRE_EQUAL(container->getFiles().size(), 1);
+    File dummyFile({File::Type::FIFO, "dummy", 1, 2});
+    BOOST_REQUIRE_THROW(container->removeFile(dummyFile), ProvisionException);
+    BOOST_REQUIRE_NO_THROW(container->removeFile(fileList[1]));
+    BOOST_REQUIRE_EQUAL(container->getFiles().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(AddDeclareMount)
+{
+    container->declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake");
+    container->declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake");
+    BOOST_CHECK_THROW(container->declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake"),
+                      ProvisionException);
+
+    std::vector<Mount> mountList = container->getMounts();
+    BOOST_REQUIRE_EQUAL(mountList.size(), 2);
+
+    BOOST_REQUIRE(mountList[0].source == "/fake/path1");
+    BOOST_REQUIRE(mountList[0].target == "/fake/path2");
+    BOOST_REQUIRE(mountList[0].type == "tmpfs");
+    BOOST_REQUIRE(mountList[0].flags == 077);
+    BOOST_REQUIRE(mountList[0].data == "fake");
+
+    BOOST_REQUIRE(mountList[1].source == "/fake/path2");
+    BOOST_REQUIRE(mountList[1].target == "/fake/path2");
+    BOOST_REQUIRE(mountList[1].type == "tmpfs");
+    BOOST_REQUIRE(mountList[1].flags == 077);
+    BOOST_REQUIRE(mountList[1].data == "fake");
+
+    BOOST_REQUIRE_NO_THROW(container->removeMount(mountList[0]));
+    BOOST_REQUIRE_EQUAL(container->getMounts().size(), 1);
+    Mount dummyMount({"a", "b", "c", 1, "d"});
+    BOOST_REQUIRE_THROW(container->removeMount(dummyMount), ProvisionException);
+    BOOST_REQUIRE_NO_THROW(container->removeMount(mountList[1]));
+    BOOST_REQUIRE_EQUAL(container->getMounts().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(AddDeclareLink)
+{
+    container->declareLink("/fake/path1", "/fake/path2");
+    container->declareLink("/fake/path2", "/fake/path2");
+    BOOST_CHECK_THROW(container->declareLink("/fake/path2", "/fake/path2"),
+                      ProvisionException);
+
+    std::vector<Link> linkList = container->getLinks();
+    BOOST_REQUIRE_EQUAL(linkList.size(), 2);
+
+    BOOST_REQUIRE(linkList[0].source == "/fake/path1");
+    BOOST_REQUIRE(linkList[0].target == "/fake/path2");
+    BOOST_REQUIRE(linkList[1].source == "/fake/path2");
+    BOOST_REQUIRE(linkList[1].target == "/fake/path2");
+
+    BOOST_REQUIRE_NO_THROW(container->removeLink(linkList[0]));
+    BOOST_REQUIRE_EQUAL(container->getLinks().size(), 1);
+    Link dummyLink({"a", "b"});
+    BOOST_REQUIRE_THROW(container->removeLink(dummyLink), ProvisionException);
+    BOOST_REQUIRE_NO_THROW(container->removeLink(linkList[1]));
+    BOOST_REQUIRE_EQUAL(container->getLinks().size(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(ProvisioningConfigSerialization)
+{
+    std::string tmpConfigFile = "/tmp/fileconfig.conf";
+    std::string tmpConfigMount = "/tmp/mountconfig.conf";
+    std::string tmpConfigLink = "/tmp/linkconfig.conf";
+
+    File  saved_file ({File::Type::REGULAR, "path", 0747, 0777});
+    Mount saved_mount({"/fake/path1", "/fake/path2", "tmpfs", 077, "fake"});
+    Link  saved_link ({"/fake/path1", "/fake/path2"});
+    config::saveToJsonFile(tmpConfigFile, saved_file);
+    config::saveToJsonFile(tmpConfigMount, saved_mount);
+    config::saveToJsonFile(tmpConfigLink, saved_link);
+
+    File loaded_file;
+    Mount loaded_mount;
+    Link loaded_link;
+    config::loadFromJsonFile(tmpConfigFile, loaded_file);
+    config::loadFromJsonFile(tmpConfigMount, loaded_mount);
+    config::loadFromJsonFile(tmpConfigLink, loaded_link);
+    BOOST_REQUIRE(saved_file == loaded_file);
+    BOOST_REQUIRE(saved_mount == loaded_mount);
+    BOOST_REQUIRE(saved_link == loaded_link);
+}
+
+BOOST_AUTO_TEST_SUITE_END()