2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Jan Olszak <j.olszak@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 Jan Olszak (j.olszak@samsung.com)
22 * @brief Implementation of class for administrating one zone
27 #include "zone-admin.hpp"
28 #include "exception.hpp"
30 #include "logger/logger.hpp"
31 #include "utils/paths.hpp"
32 #include "utils/c-array.hpp"
33 #include "lxc/cgroup.hpp"
43 // TODO: this should be in zone's configuration file
44 const int SHUTDOWN_WAIT = 10;
48 const std::uint64_t DEFAULT_CPU_SHARES = 1024;
49 const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
51 ZoneAdmin::ZoneAdmin(const std::string& zoneId,
52 const std::string& zonesPath,
53 const std::string& lxcTemplatePrefix,
54 const ZoneConfig& config,
55 const ZoneDynamicConfig& dynamicConfig)
57 mZone(zonesPath, zoneId),
62 LOGD(mId << ": Instantiating ZoneAdmin object");
64 if (!mZone.isDefined()) {
66 const std::string lxcTemplate = utils::getAbsolutePath(config.lxcTemplate,
68 LOGI(mId << ": Creating zone from template: " << lxcTemplate);
69 utils::CStringArrayBuilder args;
70 if (!dynamicConfig.ipv4Gateway.empty()) {
71 args.add("--ipv4-gateway");
72 args.add(dynamicConfig.ipv4Gateway.c_str());
74 if (!dynamicConfig.ipv4.empty()) {
76 args.add(dynamicConfig.ipv4.c_str());
78 const std::string vt = std::to_string(dynamicConfig.vt);
79 if (dynamicConfig.vt > 0) {
83 if (!mZone.create(lxcTemplate, args.c_array())) {
84 throw ZoneOperationException("Could not create zone");
90 ZoneAdmin::~ZoneAdmin()
92 LOGD(mId << ": Destroying ZoneAdmin object...");
96 LOGE(mId << ": Failed to stop the zone");
98 if (!mZone.destroy()) {
99 LOGE(mId << ": Failed to destroy the zone");
103 if (!mDetachOnExit) {
104 // Try to forcefully stop
106 LOGE(mId << ": Failed to stop the zone");
110 LOGD(mId << ": ZoneAdmin object destroyed");
114 const std::string& ZoneAdmin::getId() const
120 void ZoneAdmin::start()
122 LOGD(mId << ": Starting...");
124 LOGD(mId << ": Already running - nothing to do...");
128 utils::CStringArrayBuilder args;
129 for (const std::string& arg : mConfig.initWithArgs) {
130 args.add(arg.c_str());
133 args.add("/sbin/init");
136 if (!mZone.start(args.c_array())) {
137 throw ZoneOperationException("Could not start zone");
140 LOGD(mId << ": Started");
144 void ZoneAdmin::stop()
146 LOGD(mId << ": Stopping procedure started...");
148 LOGD(mId << ": Already crashed/down/off - nothing to do");
152 if (!mZone.shutdown(SHUTDOWN_WAIT)) {
155 throw ZoneOperationException("Could not stop zone");
159 LOGD(mId << ": Stopping procedure ended");
163 void ZoneAdmin::destroy()
165 LOGD(mId << ": Destroying procedure started...");
167 if (!mZone.destroy()) {
168 throw ZoneOperationException("Could not destroy zone");
171 LOGD(mId << ": Destroying procedure ended");
175 bool ZoneAdmin::isRunning()
177 return mZone.getState() == lxc::LxcZone::State::RUNNING;
181 bool ZoneAdmin::isStopped()
183 return mZone.getState() == lxc::LxcZone::State::STOPPED;
187 void ZoneAdmin::suspend()
189 LOGD(mId << ": Pausing...");
190 if (!mZone.freeze()) {
191 throw ZoneOperationException("Could not pause zone");
193 LOGD(mId << ": Paused");
197 void ZoneAdmin::resume()
199 LOGD(mId << ": Resuming...");
200 if (!mZone.unfreeze()) {
201 throw ZoneOperationException("Could not resume zone");
203 LOGD(mId << ": Resumed");
207 bool ZoneAdmin::isPaused()
209 return mZone.getState() == lxc::LxcZone::State::FROZEN;
213 void ZoneAdmin::setSchedulerLevel(SchedulerLevel sched)
218 case SchedulerLevel::FOREGROUND:
219 LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
220 setSchedulerParams(DEFAULT_CPU_SHARES,
221 DEFAULT_VCPU_PERIOD_MS,
222 mConfig.cpuQuotaForeground);
224 case SchedulerLevel::BACKGROUND:
225 LOGD(mId << ": Setting SchedulerLevel::BACKGROUND");
226 setSchedulerParams(DEFAULT_CPU_SHARES,
227 DEFAULT_VCPU_PERIOD_MS,
228 mConfig.cpuQuotaBackground);
231 assert(0 && "Unknown sched parameter value");
236 void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares,
237 std::uint64_t vcpuPeriod,
238 std::int64_t vcpuQuota)
240 assert(vcpuPeriod >= 1000 && vcpuPeriod <= 1000000);
241 assert(vcpuQuota == -1 ||
242 (vcpuQuota >= 1000 && vcpuQuota <= static_cast<std::int64_t>(ULLONG_MAX / 1000)));
244 if (!lxc::setCgroup(mId, "cpu", "cpu.shares", std::to_string(cpuShares)) ||
245 !lxc::setCgroup(mId, "cpu", "cpu.cfs_period_us", std::to_string(vcpuPeriod)) ||
246 !lxc::setCgroup(mId, "cpu", "cpu.cfs_quota_us", std::to_string(vcpuQuota))) {
248 LOGE(mId << ": Error while setting the zone's scheduler params");
249 throw ZoneOperationException("Could not set scheduler params");
253 void ZoneAdmin::setDetachOnExit()
255 mDetachOnExit = true;
258 void ZoneAdmin::setDestroyOnExit()
260 mDestroyOnExit = true;
263 std::int64_t ZoneAdmin::getSchedulerQuota()
266 if (!lxc::getCgroup(mId, "cpu", "cpu.cfs_quota_us", ret)) {
267 LOGE(mId << ": Error while getting the zone's scheduler quota param");
268 throw ZoneOperationException("Could not get scheduler quota param");
270 return std::stoll(ret);
273 void ZoneAdmin::createNetdevVeth(const std::string& /* zoneDev */,
274 const std::string& /* hostDev */)
276 throw ZoneOperationException("Not implemented");
279 void ZoneAdmin::createNetdevMacvlan(const std::string& /* zoneDev */,
280 const std::string& /* hostDev */,
281 const uint32_t& /* mode */)
283 throw ZoneOperationException("Not implemented");
286 void ZoneAdmin::moveNetdev(const std::string& /* devId */)
288 throw ZoneOperationException("Not implemented");