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"
31 #include "logger/logger.hpp"
32 #include "utils/paths.hpp"
33 #include "utils/c-array.hpp"
34 #include "lxc/cgroup.hpp"
44 const std::uint64_t DEFAULT_CPU_SHARES = 1024;
45 const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
47 ZoneAdmin::ZoneAdmin(const std::string& zoneId,
48 const std::string& zonesPath,
49 const std::string& zoneTemplatePrefix,
50 const ZoneConfig& config,
51 const ZoneDynamicConfig& dynamicConfig)
53 mDynamicConfig(dynamicConfig),
54 mZone(zonesPath, zoneId),
59 LOGD(mId << ": Instantiating ZoneAdmin object");
61 if (!mZone.isDefined()) {
63 const std::string zoneTemplate = utils::getAbsolutePath(config.zoneTemplate,
65 LOGI(mId << ": Creating zone from template: " << zoneTemplate);
66 utils::CStringArrayBuilder args;
67 if (!dynamicConfig.ipv4Gateway.empty()) {
68 args.add("--ipv4-gateway");
69 args.add(dynamicConfig.ipv4Gateway.c_str());
71 if (!dynamicConfig.ipv4.empty()) {
73 args.add(dynamicConfig.ipv4.c_str());
75 const std::string vt = std::to_string(dynamicConfig.vt);
76 if (dynamicConfig.vt > 0) {
80 if (!mZone.create(zoneTemplate, args.c_array())) {
81 throw ZoneOperationException("Could not create zone");
87 ZoneAdmin::~ZoneAdmin()
89 LOGD(mId << ": Destroying ZoneAdmin object...");
93 LOGE(mId << ": Failed to stop the zone");
95 if (!mZone.destroy()) {
96 LOGE(mId << ": Failed to destroy the zone");
100 if (!mDetachOnExit) {
101 // Try to forcefully stop
103 LOGE(mId << ": Failed to stop the zone");
107 LOGD(mId << ": ZoneAdmin object destroyed");
111 const std::string& ZoneAdmin::getId() const
117 void ZoneAdmin::start()
119 LOGD(mId << ": Starting...");
121 LOGD(mId << ": Already running - nothing to do...");
125 utils::CStringArrayBuilder args;
126 for (const std::string& arg : mConfig.initWithArgs) {
127 args.add(arg.c_str());
130 args.add("/sbin/init");
133 if (!mZone.start(args.c_array())) {
134 throw ZoneOperationException("Could not start zone");
137 // Wait until the full platform launch with graphical stack.
138 // VT should be activated by a graphical stack.
139 // If we do it with 'zoneToFocus.activateVT' before starting the graphical stack,
140 // graphical stack initialization failed and we finally switch to the black screen.
141 // Skip waiting when graphical stack is not running (unit tests).
142 if (mDynamicConfig.vt > 0) {
143 // TODO, timeout is a temporary solution
144 std::this_thread::sleep_for(std::chrono::milliseconds(4000));
147 LOGD(mId << ": Started");
151 void ZoneAdmin::stop()
153 LOGD(mId << ": Stopping procedure started...");
155 LOGD(mId << ": Already crashed/down/off - nothing to do");
159 if (!mZone.shutdown(mConfig.shutdownTimeout)) {
162 throw ZoneOperationException("Could not stop zone");
166 LOGD(mId << ": Stopping procedure ended");
170 void ZoneAdmin::destroy()
172 LOGD(mId << ": Destroying procedure started...");
174 if (!mZone.destroy()) {
175 throw ZoneOperationException("Could not destroy zone");
178 LOGD(mId << ": Destroying procedure ended");
182 bool ZoneAdmin::isRunning()
184 return mZone.getState() == lxc::LxcZone::State::RUNNING;
188 bool ZoneAdmin::isStopped()
190 return mZone.getState() == lxc::LxcZone::State::STOPPED;
194 void ZoneAdmin::suspend()
196 LOGD(mId << ": Pausing...");
197 if (!mZone.freeze()) {
198 throw ZoneOperationException("Could not pause zone");
200 LOGD(mId << ": Paused");
204 void ZoneAdmin::resume()
206 LOGD(mId << ": Resuming...");
207 if (!mZone.unfreeze()) {
208 throw ZoneOperationException("Could not resume zone");
210 LOGD(mId << ": Resumed");
214 bool ZoneAdmin::isPaused()
216 return mZone.getState() == lxc::LxcZone::State::FROZEN;
220 void ZoneAdmin::setSchedulerLevel(SchedulerLevel sched)
225 case SchedulerLevel::FOREGROUND:
226 LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
227 setSchedulerParams(DEFAULT_CPU_SHARES,
228 DEFAULT_VCPU_PERIOD_MS,
229 mConfig.cpuQuotaForeground);
231 case SchedulerLevel::BACKGROUND:
232 LOGD(mId << ": Setting SchedulerLevel::BACKGROUND");
233 setSchedulerParams(DEFAULT_CPU_SHARES,
234 DEFAULT_VCPU_PERIOD_MS,
235 mConfig.cpuQuotaBackground);
238 assert(0 && "Unknown sched parameter value");
243 void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares,
244 std::uint64_t vcpuPeriod,
245 std::int64_t vcpuQuota)
247 assert(vcpuPeriod >= 1000 && vcpuPeriod <= 1000000);
248 assert(vcpuQuota == -1 ||
249 (vcpuQuota >= 1000 && vcpuQuota <= static_cast<std::int64_t>(ULLONG_MAX / 1000)));
251 if (!lxc::setCgroup(mId, "cpu", "cpu.shares", std::to_string(cpuShares)) ||
252 !lxc::setCgroup(mId, "cpu", "cpu.cfs_period_us", std::to_string(vcpuPeriod)) ||
253 !lxc::setCgroup(mId, "cpu", "cpu.cfs_quota_us", std::to_string(vcpuQuota))) {
255 LOGE(mId << ": Error while setting the zone's scheduler params");
256 throw ZoneOperationException("Could not set scheduler params");
260 void ZoneAdmin::setDetachOnExit()
262 mDetachOnExit = true;
265 void ZoneAdmin::setDestroyOnExit()
267 mDestroyOnExit = true;
270 std::int64_t ZoneAdmin::getSchedulerQuota()
273 if (!lxc::getCgroup(mId, "cpu", "cpu.cfs_quota_us", ret)) {
274 LOGE(mId << ": Error while getting the zone's scheduler quota param");
275 throw ZoneOperationException("Could not get scheduler quota param");
277 return std::stoll(ret);
280 void ZoneAdmin::createNetdevVeth(const std::string& zoneDev,
281 const std::string& hostDev)
283 netdev::createVeth(mZone.getInitPid(), zoneDev, hostDev);
286 void ZoneAdmin::createNetdevMacvlan(const std::string& zoneDev,
287 const std::string& hostDev,
288 const uint32_t& mode)
290 netdev::createMacvlan(mZone.getInitPid(), zoneDev, hostDev, static_cast<macvlan_mode>(mode));
293 void ZoneAdmin::moveNetdev(const std::string& devId)
295 netdev::movePhys(mZone.getInitPid(), devId);
298 void ZoneAdmin::destroyNetdev(const std::string& devId)
300 netdev::destroyNetdev(devId, mZone.getInitPid());
303 void ZoneAdmin::setNetdevAttrs(const std::string& netdev, const NetdevAttrs& attrs)
305 netdev::setAttrs(mZone.getInitPid(), netdev, attrs);
308 ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& netdev)
310 return netdev::getAttrs(mZone.getInitPid(), netdev);
313 std::vector<std::string> ZoneAdmin::getNetdevList()
315 return netdev::listNetdev(mZone.getInitPid());
318 void ZoneAdmin::deleteNetdevIpAddress(const std::string& netdev, const std::string& ip)
320 netdev::deleteIpAddress(mZone.getInitPid(), netdev, ip);