2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Mateusz Malicki <m.malicki2@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
21 * @author Mateusz Malicki (m.malicki2@samsung.com)
22 * @brief Implementation of class for managing zone provsion
27 #include "zone-provision.hpp"
28 #include "zone-provision-config.hpp"
30 #include "logger/logger.hpp"
31 #include "utils/fs.hpp"
32 #include "utils/exception.hpp"
33 #include "config/manager.hpp"
34 #include "vasum-client.h"
36 #include <boost/filesystem.hpp>
42 namespace fs = boost::filesystem;
44 using namespace utils;
48 ZoneProvision::ZoneProvision(const std::string& rootPath,
49 const std::string& configPath,
50 const std::string& dbPath,
51 const std::string& dbPrefix,
52 const std::vector<std::string>& validLinkPrefixes)
56 , mValidLinkPrefixes(validLinkPrefixes)
58 config::loadFromKVStoreWithJsonFile(dbPath, configPath, mProvisioningConfig, dbPrefix);
61 ZoneProvision::~ZoneProvision()
66 void ZoneProvision::saveProvisioningConfig()
68 config::saveToKVStore(mDbPath, mProvisioningConfig, mDbPrefix);
71 std::string ZoneProvision::declareProvision(ZoneProvisioningConfig::Provision&& provision)
73 std::string id = getId(provision);
74 auto it = std::find_if(mProvisioningConfig.provisions.begin(),
75 mProvisioningConfig.provisions.end(),
76 [&](const ZoneProvisioningConfig::Provision& existingProvision) {
77 return getId(existingProvision) == id;
79 if (it != mProvisioningConfig.provisions.end()) {
80 const std::string msg = "Can't add provision. It already exists: " + id;
82 throw ProvisionExistsException(msg);
84 mProvisioningConfig.provisions.push_back(std::move(provision));
85 saveProvisioningConfig();
89 std::string ZoneProvision::declareFile(const int32_t& type,
90 const std::string& path,
94 ZoneProvisioningConfig::Provision provision;
95 provision.set(ZoneProvisioningConfig::File({type, path, flags, mode}));
97 return declareProvision(std::move(provision));
100 std::string ZoneProvision::declareMount(const std::string& source,
101 const std::string& target,
102 const std::string& type,
103 const int64_t& flags,
104 const std::string& data)
106 ZoneProvisioningConfig::Provision provision;
107 provision.set(ZoneProvisioningConfig::Mount({source, target, type, flags, data}));
109 return declareProvision(std::move(provision));
112 std::string ZoneProvision::declareLink(const std::string& source,
113 const std::string& target)
115 ZoneProvisioningConfig::Provision provision;
116 provision.set(ZoneProvisioningConfig::Link({source, target}));
118 return declareProvision(std::move(provision));
121 void ZoneProvision::start() noexcept
123 for (const auto& provision : mProvisioningConfig.provisions) {
125 if (provision.is<ZoneProvisioningConfig::File>()) {
126 file(provision.as<ZoneProvisioningConfig::File>());
127 } else if (provision.is<ZoneProvisioningConfig::Mount>()) {
128 mount(provision.as<ZoneProvisioningConfig::Mount>());
129 } else if (provision.is<ZoneProvisioningConfig::Link>()) {
130 link(provision.as<ZoneProvisioningConfig::Link>());
132 // mProvisioned must be FILO
133 mProvisioned.push_front(provision);
134 } catch (const std::exception& ex) {
135 LOGE("Provsion error: " << ex.what());
140 void ZoneProvision::stop() noexcept
142 mProvisioned.remove_if([this](const ZoneProvisioningConfig::Provision& provision) -> bool {
144 if (provision.is<ZoneProvisioningConfig::Mount>()) {
145 umount(provision.as<ZoneProvisioningConfig::Mount>());
147 // leaves files, links, fifo, untouched
149 } catch (const std::exception& ex) {
150 LOGE("Provsion error: " << ex.what());
156 std::vector<std::string> ZoneProvision::list() const
158 std::vector<std::string> items;
159 for (const auto& provision : mProvisioningConfig.provisions) {
160 items.push_back(getId(provision));
165 void ZoneProvision::remove(const std::string& item)
168 const auto it = std::find_if(mProvisioningConfig.provisions.begin(),
169 mProvisioningConfig.provisions.end(),
170 [&](const ZoneProvisioningConfig::Provision& provision) {
171 return getId(provision) == item;
173 if (it == mProvisioningConfig.provisions.end()) {
174 throw UtilsException("Can't find provision");
177 mProvisioningConfig.provisions.erase(it);
178 LOGI("Provision removed: " << item);
181 void ZoneProvision::file(const ZoneProvisioningConfig::File& config)
184 const fs::path hostPath = fs::path(mRootPath) / fs::path(config.path);
185 switch (config.type) {
186 case VSMFILE_DIRECTORY:
187 ret = utils::createDirs(hostPath.string(), config.mode);
189 throw UtilsException("Can't create dir: " + hostPath.string());
194 ret = utils::createFifo(hostPath.string(), config.mode);
196 throw UtilsException("Failed to make fifo: " + config.path);
200 case VSMFILE_REGULAR:
201 if ((config.flags & O_CREAT)) {
202 ret = utils::createFile(hostPath.string(), config.flags, config.mode);
204 throw UtilsException("Failed to create file: " + config.path);
207 ret = utils::copyFile(config.path, hostPath.string());
209 throw UtilsException("Failed to copy file: " + config.path);
216 void ZoneProvision::mount(const ZoneProvisioningConfig::Mount& config)
218 const fs::path hostPath = fs::path(mRootPath) / fs::path(config.target);
219 bool ret = utils::mount(config.source,
225 throw UtilsException("Mount operation failure - source : " + config.source);
229 void ZoneProvision::umount(const ZoneProvisioningConfig::Mount& config)
231 const fs::path hostPath = fs::path(mRootPath) / fs::path(config.target);
232 bool ret = utils::umount(hostPath.string());
234 throw UtilsException("Umount operation failure - path : " + config.target);
238 void ZoneProvision::link(const ZoneProvisioningConfig::Link& config)
240 const std::string srcHostPath = fs::path(config.source).normalize().string();
241 for (const std::string& prefix : mValidLinkPrefixes) {
242 if (prefix.length() <= srcHostPath.length()
243 && srcHostPath.compare(0, prefix.length(), prefix) == 0) {
245 const fs::path destHostPath = fs::path(mRootPath) / fs::path(config.target);
246 bool ret = utils::createLink(srcHostPath, destHostPath.string());
248 throw UtilsException("Failed to create hard link: " + config.source);
253 const std::string msg = "Failed to create hard link: path=host: " +
254 srcHostPath + ", msg: Path prefix is not valid path";
256 throw UtilsException(msg);
259 std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file)
261 //TODO output of type,flags and mode should be more user friendly
264 std::to_string(file.type) + " " +
265 std::to_string(file.flags) + " " +
266 std::to_string(file.mode);
269 std::string ZoneProvision::getId(const ZoneProvisioningConfig::Mount& mount)
271 //TODO output of flags should be more user friendly
276 std::to_string(mount.flags) + " " +
280 std::string ZoneProvision::getId(const ZoneProvisioningConfig::Link& link)
282 return "link " + link.source + " " + link.target;
285 std::string ZoneProvision::getId(const ZoneProvisioningConfig::Provision& provision)
287 using namespace vasum;
288 if (provision.is<ZoneProvisioningConfig::File>()) {
289 return getId(provision.as<ZoneProvisioningConfig::File>());
290 } else if (provision.is<ZoneProvisioningConfig::Mount>()) {
291 return getId(provision.as<ZoneProvisioningConfig::Mount>());
292 } else if (provision.is<ZoneProvisioningConfig::Link>()) {
293 return getId(provision.as<ZoneProvisioningConfig::Link>());
295 throw UtilsException("Unknown provision type");