#include <boost/filesystem.hpp>
#include <string>
+#include <algorithm>
#include <fcntl.h>
namespace fs = boost::filesystem;
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
});
}
+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;
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
/**
* 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;
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
}
}
-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
/**
* 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
}
};
+std::function<bool(const std::exception&)> expectedMessage(const std::string& message) {
+ return [=](const std::exception& e) {
+ return e.what() == message;
+ };
+}
+
} // namespace
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);
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()