Add list and remove to ZoneProvision class 02/34402/10
authorMateusz Malicki <m.malicki2@samsung.com>
Mon, 26 Jan 2015 14:40:57 +0000 (15:40 +0100)
committerMateusz Malicki <m.malicki2@samsung.com>
Tue, 27 Jan 2015 15:35:57 +0000 (16:35 +0100)
[Bug/Feature]   Ability to list and remove provision
[Cause]         N/A
[Solution]      N/A
[Verification]  Build, run tests

Change-Id: I3e3a566dd00298d4111fb9a3b5ec6d2351774ac7

server/zone-provision.cpp
server/zone-provision.hpp
server/zone.cpp
server/zone.hpp
tests/unit_tests/server/ut-zone-provision.cpp

index 928d887..861a506 100644 (file)
@@ -36,6 +36,7 @@
 #include <boost/filesystem.hpp>
 
 #include <string>
+#include <algorithm>
 #include <fcntl.h>
 
 namespace fs = boost::filesystem;
@@ -65,42 +66,53 @@ void ZoneProvision::saveProvisioningConfig()
     config::saveToKVStore(mDbPath, mProvisioningConfig, mDbPrefix);
 }
 
-void ZoneProvision::declareProvision(ZoneProvisioningConfig::Provision&& provision)
+std::string ZoneProvision::declareProvision(ZoneProvisioningConfig::Provision&& provision)
 {
+    std::string id = getId(provision);
+    auto it = std::find_if(mProvisioningConfig.provisions.begin(),
+                           mProvisioningConfig.provisions.end(),
+                           [&](const ZoneProvisioningConfig::Provision& provision) {
+                               return getId(provision) == id;
+                           });
+    if (it != mProvisioningConfig.provisions.end()) {
+        LOGE("Can't add provision. It already exists: " << id);
+        throw UtilsException("Provision already exists");
+    }
     mProvisioningConfig.provisions.push_back(std::move(provision));
     saveProvisioningConfig();
+    return id;
 }
 
-void ZoneProvision::declareFile(const int32_t& type,
-                                const std::string& path,
-                                const int32_t& flags,
-                                const int32_t& mode)
+std::string ZoneProvision::declareFile(const int32_t& type,
+                                       const std::string& path,
+                                       const int32_t& flags,
+                                       const int32_t& mode)
 {
     ZoneProvisioningConfig::Provision provision;
     provision.set(ZoneProvisioningConfig::File({type, path, flags, mode}));
 
-    declareProvision(std::move(provision));
+    return declareProvision(std::move(provision));
 }
 
-void ZoneProvision::declareMount(const std::string& source,
-                                 const std::string& target,
-                                 const std::string& type,
-                                 const int64_t& flags,
-                                 const std::string& data)
+std::string ZoneProvision::declareMount(const std::string& source,
+                                        const std::string& target,
+                                        const std::string& type,
+                                        const int64_t& flags,
+                                        const std::string& data)
 {
     ZoneProvisioningConfig::Provision provision;
     provision.set(ZoneProvisioningConfig::Mount({source, target, type, flags, data}));
 
-    declareProvision(std::move(provision));
+    return declareProvision(std::move(provision));
 }
 
-void ZoneProvision::declareLink(const std::string& source,
-                                const std::string& target)
+std::string ZoneProvision::declareLink(const std::string& source,
+                                       const std::string& target)
 {
     ZoneProvisioningConfig::Provision provision;
     provision.set(ZoneProvisioningConfig::Link({source, target}));
 
-    declareProvision(std::move(provision));
+    return declareProvision(std::move(provision));
 }
 
 void ZoneProvision::start() noexcept
@@ -138,6 +150,31 @@ void ZoneProvision::stop() noexcept
     });
 }
 
+std::vector<std::string> ZoneProvision::list() const
+{
+    std::vector<std::string> items;
+    for (const auto& provision : mProvisioningConfig.provisions) {
+        items.push_back(getId(provision));
+    }
+    return items;
+}
+
+void ZoneProvision::remove(const std::string& item)
+{
+
+    const auto it = std::find_if(mProvisioningConfig.provisions.begin(),
+                                 mProvisioningConfig.provisions.end(),
+                                 [&](const ZoneProvisioningConfig::Provision& provision) {
+                                    return getId(provision) == item;
+                                 });
+    if (it == mProvisioningConfig.provisions.end()) {
+        throw UtilsException("Can't find provision");
+    }
+
+    mProvisioningConfig.provisions.erase(it);
+    LOGI("Provision removed: " << item);
+}
+
 void ZoneProvision::file(const ZoneProvisioningConfig::File& config)
 {
     bool ret = false;
@@ -216,4 +253,43 @@ void ZoneProvision::link(const ZoneProvisioningConfig::Link& config)
     throw UtilsException("Failed to hard link: path prefix is not valid");
 }
 
+std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file) const
+{
+    //TODO output of type,flags and mode should be more user friendly
+    return "file " +
+           file.path + " " +
+           std::to_string(file.type) + " " +
+           std::to_string(file.flags) + " " +
+           std::to_string(file.mode);
+}
+
+std::string ZoneProvision::getId(const ZoneProvisioningConfig::Mount& mount) const
+{
+    //TODO output of flags should be more user friendly
+    return "mount " +
+           mount.source + " " +
+           mount.target + " " +
+           mount.type + " " +
+           std::to_string(mount.flags) + " " +
+           mount.data;
+}
+
+std::string ZoneProvision::getId(const ZoneProvisioningConfig::Link& link) const
+{
+    return "link " + link.source + " " + link.target;
+}
+
+std::string ZoneProvision::getId(const ZoneProvisioningConfig::Provision& provision) const
+{
+    using namespace vasum;
+    if (provision.is<ZoneProvisioningConfig::File>()) {
+        return getId(provision.as<ZoneProvisioningConfig::File>());
+    } else if (provision.is<ZoneProvisioningConfig::Mount>()) {
+        return getId(provision.as<ZoneProvisioningConfig::Mount>());
+    } else if (provision.is<ZoneProvisioningConfig::Link>()) {
+        return getId(provision.as<ZoneProvisioningConfig::Link>());
+    }
+    throw UtilsException("Unknown provision type");
+}
+
 } // namespace vasum
index f6933db..2f123ae 100644 (file)
@@ -64,27 +64,39 @@ public:
     /**
      * Declare file, directory or pipe that will be created while zone startup
      */
-    void declareFile(const int32_t& type,
-                     const std::string& path,
-                     const int32_t& flags,
-                     const int32_t& mode);
+    std::string declareFile(const int32_t& type,
+                            const std::string& path,
+                            const int32_t& flags,
+                            const int32_t& mode);
     /**
      * Declare mount that will be created while zone startup
      */
-    void declareMount(const std::string& source,
-                      const std::string& target,
-                      const std::string& type,
-                      const int64_t& flags,
-                      const std::string& data);
+    std::string 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 zone startup
      */
-    void declareLink(const std::string& source,
-                     const std::string& target);
+    std::string declareLink(const std::string& source,
+                            const std::string& target);
 
     void start() noexcept;
     void stop() noexcept;
 
+    /**
+     * List all provisioned resources
+     */
+    std::vector<std::string> list() const;
+
+    /**
+     * Remove resource
+     *
+     * @param item resource to be removed (as in list())
+     */
+    void remove(const std::string& item);
+
 private:
     ZoneProvisioningConfig mProvisioningConfig;
     std::string mRootPath;
@@ -94,14 +106,18 @@ private:
     std::list<ZoneProvisioningConfig::Provision> mProvisioned;
 
     void saveProvisioningConfig();
-    void declareProvision(ZoneProvisioningConfig::Provision&& provision);
+    std::string declareProvision(ZoneProvisioningConfig::Provision&& provision);
 
     void mount(const ZoneProvisioningConfig::Mount& config);
     void umount(const ZoneProvisioningConfig::Mount& config);
     void file(const ZoneProvisioningConfig::File& config);
     void link(const ZoneProvisioningConfig::Link& config);
-};
 
+    std::string getId(const ZoneProvisioningConfig::File& file) const;
+    std::string getId(const ZoneProvisioningConfig::Mount& mount) const;
+    std::string getId(const ZoneProvisioningConfig::Link& link) const;
+    std::string getId(const ZoneProvisioningConfig::Provision& provision) const;
+};
 
 } // namespace vasum
 
index fbbd819..c3f6991 100644 (file)
@@ -381,27 +381,27 @@ void Zone::proxyCallAsync(const std::string& busName,
     }
 }
 
-void Zone::declareFile(const int32_t& type,
-                       const std::string& path,
-                       const int32_t& flags,
-                       const int32_t& mode)
+std::string Zone::declareFile(const int32_t& type,
+                              const std::string& path,
+                              const int32_t& flags,
+                              const int32_t& mode)
 {
-    mProvision->declareFile(type, path, flags, mode);
+    return mProvision->declareFile(type, path, flags, mode);
 }
 
-void Zone::declareMount(const std::string& source,
-                        const std::string& target,
-                        const std::string& type,
-                        const int64_t& flags,
-                        const std::string& data)
+std::string Zone::declareMount(const std::string& source,
+                               const std::string& target,
+                               const std::string& type,
+                               const int64_t& flags,
+                               const std::string& data)
 {
-    mProvision->declareMount(source, target, type, flags, data);
+    return mProvision->declareMount(source, target, type, flags, data);
 }
 
-void Zone::declareLink(const std::string& source,
-                       const std::string& target)
+std::string Zone::declareLink(const std::string& source,
+                              const std::string& target)
 {
-    mProvision->declareLink(source, target);
+    return mProvision->declareLink(source, target);
 }
 
 } // namespace vasum
index 2eab7f3..8cd3535 100644 (file)
@@ -230,23 +230,23 @@ public:
     /**
      * Declare file, directory or pipe that will be created while zone startup
      */
-    void declareFile(const int32_t& type,
-                     const std::string& path,
-                     const int32_t& flags,
-                     const int32_t& mode);
+    std::string declareFile(const int32_t& type,
+                            const std::string& path,
+                            const int32_t& flags,
+                            const int32_t& mode);
     /**
      * Declare mount that will be created while zone startup
      */
-    void declareMount(const std::string& source,
-                      const std::string& target,
-                      const std::string& type,
-                      const int64_t& flags,
-                      const std::string& data);
+    std::string 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 zone startup
      */
-    void declareLink(const std::string& source,
-                     const std::string& target);
+    std::string declareLink(const std::string& source,
+                            const std::string& target);
 
    /**
      * Get zone root path
index c488c09..9038fd4 100644 (file)
@@ -89,6 +89,12 @@ struct Fixture {
     }
 };
 
+std::function<bool(const std::exception&)> expectedMessage(const std::string& message) {
+    return [=](const std::exception& e) {
+        return e.what() == message;
+    };
+}
+
 } // namespace
 
 
@@ -257,6 +263,9 @@ BOOST_AUTO_TEST_CASE(DeclareMountTest)
     ZoneProvision zoneProvision = create({});
     zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake");
     zoneProvision.declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake");
+    BOOST_CHECK_EXCEPTION(zoneProvision.declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake"),
+                          UtilsException,
+                          expectedMessage("Provision already exists"));
 
     ZoneProvisioningConfig config;
     load(config);
@@ -338,4 +347,64 @@ BOOST_AUTO_TEST_CASE(ProvisionedAlreadyTest)
     zoneProvision.stop();
 }
 
+BOOST_AUTO_TEST_CASE(ListTest)
+{
+    std::vector<std::string> expected;
+    ZoneProvision zoneProvision = create({});
+
+    zoneProvision.declareFile(1, "path", 0747, 0777);
+    zoneProvision.declareFile(2, "path", 0747, 0777);
+    expected.push_back("file path 1 " + std::to_string(0747) + " " + std::to_string(0777));
+    expected.push_back("file path 2 " + std::to_string(0747) + " " + std::to_string(0777));
+
+    zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake1");
+    zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake2");
+    expected.push_back("mount /fake/path1 /fake/path2 tmpfs " + std::to_string(077) + " fake1");
+    expected.push_back("mount /fake/path1 /fake/path2 tmpfs " + std::to_string(077) + " fake2");
+
+    zoneProvision.declareLink("/fake/path1", "/fake/path3");
+    zoneProvision.declareLink("/fake/path2", "/fake/path4");
+    expected.push_back("link /fake/path1 /fake/path3");
+    expected.push_back("link /fake/path2 /fake/path4");
+
+    const std::vector<std::string> provisions = zoneProvision.list();
+    BOOST_REQUIRE_EQUAL(provisions.size(), expected.size());
+    auto provision = provisions.cbegin();
+    for (const auto& item : expected) {
+        BOOST_CHECK_EQUAL(item, *(provision++));
+    }
+}
+
+BOOST_AUTO_TEST_CASE(RemoveTest)
+{
+    std::vector<std::string> expected;
+    ZoneProvision zoneProvision = create({});
+
+    zoneProvision.declareFile(1, "path", 0747, 0777);
+    zoneProvision.declareFile(2, "path", 0747, 0777);
+    expected.push_back("file path 2 " + std::to_string(0747) + " " + std::to_string(0777));
+
+    zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake1");
+    zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake2");
+    expected.push_back("mount /fake/path1 /fake/path2 tmpfs " + std::to_string(077) + " fake1");
+
+    zoneProvision.declareLink("/fake/path1", "/fake/path3");
+    zoneProvision.declareLink("/fake/path2", "/fake/path4");
+    expected.push_back("link /fake/path1 /fake/path3");
+
+    zoneProvision.remove("file path 1 " + std::to_string(0747) + " " + std::to_string(0777));
+    zoneProvision.remove("mount /fake/path1 /fake/path2 tmpfs " + std::to_string(077) + " fake2");
+    zoneProvision.remove("link /fake/path2 /fake/path4");
+    BOOST_CHECK_EXCEPTION(zoneProvision.remove("link /fake/path_fake /fake/path2"),
+                          UtilsException,
+                          expectedMessage("Can't find provision"));
+
+    const std::vector<std::string> provisions = zoneProvision.list();
+    BOOST_REQUIRE_EQUAL(provisions.size(), expected.size());
+    auto provision = provisions.cbegin();
+    for (const auto& item : expected) {
+        BOOST_CHECK_EQUAL(item, *(provision++));
+    }
+}
+
 BOOST_AUTO_TEST_SUITE_END()