Stubs for get/set ipv4/ipv6, destroy netdev and list netdev
[platform/core/security/vasum.git] / server / zone-admin.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Jan Olszak <j.olszak@samsung.com>
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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
17  */
18
19 /**
20  * @file
21  * @author  Jan Olszak (j.olszak@samsung.com)
22  * @brief   Implementation of class for administrating one zone
23  */
24
25 #include "config.hpp"
26
27 #include "zone-admin.hpp"
28 #include "exception.hpp"
29 #include "netdev.hpp"
30
31 #include "logger/logger.hpp"
32 #include "utils/paths.hpp"
33 #include "utils/c-array.hpp"
34 #include "lxc/cgroup.hpp"
35
36 #include <cassert>
37 #include <climits>
38
39
40 namespace vasum {
41
42 namespace {
43
44 // TODO: this should be in zone's configuration file
45 const int SHUTDOWN_WAIT = 10;
46
47 } // namespace
48
49 const std::uint64_t DEFAULT_CPU_SHARES = 1024;
50 const std::uint64_t DEFAULT_VCPU_PERIOD_MS = 100000;
51
52 ZoneAdmin::ZoneAdmin(const std::string& zoneId,
53                      const std::string& zonesPath,
54                      const std::string& lxcTemplatePrefix,
55                      const ZoneConfig& config,
56                      const ZoneDynamicConfig& dynamicConfig)
57     : mConfig(config),
58       mZone(zonesPath, zoneId),
59       mId(zoneId),
60       mDetachOnExit(false),
61       mDestroyOnExit(false)
62 {
63     LOGD(mId << ": Instantiating ZoneAdmin object");
64
65     if (!mZone.isDefined()) {
66
67         const std::string lxcTemplate = utils::getAbsolutePath(config.lxcTemplate,
68                                                                lxcTemplatePrefix);
69         LOGI(mId << ": Creating zone from template: " << lxcTemplate);
70         utils::CStringArrayBuilder args;
71         if (!dynamicConfig.ipv4Gateway.empty()) {
72             args.add("--ipv4-gateway");
73             args.add(dynamicConfig.ipv4Gateway.c_str());
74         }
75         if (!dynamicConfig.ipv4.empty()) {
76             args.add("--ipv4");
77             args.add(dynamicConfig.ipv4.c_str());
78         }
79         const std::string vt = std::to_string(dynamicConfig.vt);
80         if (dynamicConfig.vt > 0) {
81             args.add("--vt");
82             args.add(vt.c_str());
83         }
84         if (!mZone.create(lxcTemplate, args.c_array())) {
85             throw ZoneOperationException("Could not create zone");
86         }
87     }
88 }
89
90
91 ZoneAdmin::~ZoneAdmin()
92 {
93     LOGD(mId << ": Destroying ZoneAdmin object...");
94
95     if (mDestroyOnExit) {
96         if (!mZone.stop()) {
97             LOGE(mId << ": Failed to stop the zone");
98         }
99         if (!mZone.destroy()) {
100             LOGE(mId << ": Failed to destroy the zone");
101         }
102     }
103
104     if (!mDetachOnExit) {
105         // Try to forcefully stop
106         if (!mZone.stop()) {
107             LOGE(mId << ": Failed to stop the zone");
108         }
109     }
110
111     LOGD(mId << ": ZoneAdmin object destroyed");
112 }
113
114
115 const std::string& ZoneAdmin::getId() const
116 {
117     return mId;
118 }
119
120
121 void ZoneAdmin::start()
122 {
123     LOGD(mId << ": Starting...");
124     if (isRunning()) {
125         LOGD(mId << ": Already running - nothing to do...");
126         return;
127     }
128
129     utils::CStringArrayBuilder args;
130     for (const std::string& arg : mConfig.initWithArgs) {
131         args.add(arg.c_str());
132     }
133     if (args.empty()) {
134         args.add("/sbin/init");
135     }
136
137     if (!mZone.start(args.c_array())) {
138         throw ZoneOperationException("Could not start zone");
139     }
140
141     LOGD(mId << ": Started");
142 }
143
144
145 void ZoneAdmin::stop()
146 {
147     LOGD(mId << ": Stopping procedure started...");
148     if (isStopped()) {
149         LOGD(mId << ": Already crashed/down/off - nothing to do");
150         return;
151     }
152
153     if (!mZone.shutdown(SHUTDOWN_WAIT)) {
154         // force stop
155         if (!mZone.stop()) {
156             throw ZoneOperationException("Could not stop zone");
157         }
158     }
159
160     LOGD(mId << ": Stopping procedure ended");
161 }
162
163
164 void ZoneAdmin::destroy()
165 {
166     LOGD(mId << ": Destroying procedure started...");
167
168     if (!mZone.destroy()) {
169         throw ZoneOperationException("Could not destroy zone");
170     }
171
172     LOGD(mId << ": Destroying procedure ended");
173 }
174
175
176 bool ZoneAdmin::isRunning()
177 {
178     return mZone.getState() == lxc::LxcZone::State::RUNNING;
179 }
180
181
182 bool ZoneAdmin::isStopped()
183 {
184     return mZone.getState() == lxc::LxcZone::State::STOPPED;
185 }
186
187
188 void ZoneAdmin::suspend()
189 {
190     LOGD(mId << ": Pausing...");
191     if (!mZone.freeze()) {
192         throw ZoneOperationException("Could not pause zone");
193     }
194     LOGD(mId << ": Paused");
195 }
196
197
198 void ZoneAdmin::resume()
199 {
200     LOGD(mId << ": Resuming...");
201     if (!mZone.unfreeze()) {
202         throw ZoneOperationException("Could not resume zone");
203     }
204     LOGD(mId << ": Resumed");
205 }
206
207
208 bool ZoneAdmin::isPaused()
209 {
210     return mZone.getState() == lxc::LxcZone::State::FROZEN;
211 }
212
213
214 void ZoneAdmin::setSchedulerLevel(SchedulerLevel sched)
215 {
216     assert(isRunning());
217
218     switch (sched) {
219     case SchedulerLevel::FOREGROUND:
220         LOGD(mId << ": Setting SchedulerLevel::FOREGROUND");
221         setSchedulerParams(DEFAULT_CPU_SHARES,
222                            DEFAULT_VCPU_PERIOD_MS,
223                            mConfig.cpuQuotaForeground);
224         break;
225     case SchedulerLevel::BACKGROUND:
226         LOGD(mId << ": Setting SchedulerLevel::BACKGROUND");
227         setSchedulerParams(DEFAULT_CPU_SHARES,
228                            DEFAULT_VCPU_PERIOD_MS,
229                            mConfig.cpuQuotaBackground);
230         break;
231     default:
232         assert(0 && "Unknown sched parameter value");
233     }
234 }
235
236
237 void ZoneAdmin::setSchedulerParams(std::uint64_t cpuShares,
238                                    std::uint64_t vcpuPeriod,
239                                    std::int64_t vcpuQuota)
240 {
241     assert(vcpuPeriod >= 1000 && vcpuPeriod <= 1000000);
242     assert(vcpuQuota == -1 ||
243            (vcpuQuota >= 1000 && vcpuQuota <= static_cast<std::int64_t>(ULLONG_MAX / 1000)));
244
245     if (!lxc::setCgroup(mId, "cpu", "cpu.shares", std::to_string(cpuShares)) ||
246         !lxc::setCgroup(mId, "cpu", "cpu.cfs_period_us", std::to_string(vcpuPeriod)) ||
247         !lxc::setCgroup(mId, "cpu", "cpu.cfs_quota_us", std::to_string(vcpuQuota))) {
248
249         LOGE(mId << ": Error while setting the zone's scheduler params");
250         throw ZoneOperationException("Could not set scheduler params");
251     }
252 }
253
254 void ZoneAdmin::setDetachOnExit()
255 {
256     mDetachOnExit = true;
257 }
258
259 void ZoneAdmin::setDestroyOnExit()
260 {
261     mDestroyOnExit = true;
262 }
263
264 std::int64_t ZoneAdmin::getSchedulerQuota()
265 {
266     std::string ret;
267     if (!lxc::getCgroup(mId, "cpu", "cpu.cfs_quota_us", ret)) {
268         LOGE(mId << ": Error while getting the zone's scheduler quota param");
269         throw ZoneOperationException("Could not get scheduler quota param");
270     }
271     return std::stoll(ret);
272 }
273
274 void ZoneAdmin::createNetdevVeth(const std::string& zoneDev,
275                                  const std::string& hostDev)
276 {
277     netdev::createVeth(mZone.getInitPid(), zoneDev, hostDev);
278 }
279
280 void ZoneAdmin::createNetdevMacvlan(const std::string& zoneDev,
281                                     const std::string& hostDev,
282                                     const uint32_t& mode)
283 {
284     netdev::createMacvlan(mZone.getInitPid(), zoneDev, hostDev, static_cast<macvlan_mode>(mode));
285 }
286
287 void ZoneAdmin::moveNetdev(const std::string& devId)
288 {
289     netdev::movePhys(mZone.getInitPid(), devId);
290 }
291
292 void ZoneAdmin::setNetdevAttrs(const std::string& /* netdev */, const NetdevAttrs& /* attrs */)
293 {
294     throw ZoneOperationException("Not implemented");
295 }
296
297 ZoneAdmin::NetdevAttrs ZoneAdmin::getNetdevAttrs(const std::string& /* netdev */)
298 {
299     throw ZoneOperationException("Not implemented");
300 }
301
302 std::vector<std::string> ZoneAdmin::getNetdevList()
303 {
304     throw ZoneOperationException("Not implemented");
305 }
306
307 } // namespace vasum