2 * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License version 2.1 as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * @author Mateusz Malicki (m.malicki2@samsung.com)
21 * @brief ContainerImpl definition
24 #include "lxcpp/container-impl.hpp"
25 #include "lxcpp/exception.hpp"
26 #include "lxcpp/process.hpp"
27 #include "lxcpp/filesystem.hpp"
28 #include "lxcpp/capability.hpp"
29 #include "lxcpp/commands/attach.hpp"
30 #include "lxcpp/commands/console.hpp"
31 #include "lxcpp/commands/start.hpp"
32 #include "lxcpp/commands/stop.hpp"
33 #include "lxcpp/commands/prep-host-terminal.hpp"
34 #include "lxcpp/commands/provision.hpp"
36 #include "logger/logger.hpp"
37 #include "utils/exception.hpp"
40 #include <sys/mount.h>
45 #include <ext/stdio_filebuf.h>
53 ContainerImpl::ContainerImpl(const std::string &name, const std::string &path)
56 const std::string msg = "Name cannot be empty";
58 throw ConfigureException(msg);
62 const std::string msg = "Path cannot be empty";
64 throw ConfigureException(msg);
67 if(::access(path.c_str(), X_OK) < 0) {
68 const std::string msg = "Path must point to a traversable directory";
70 throw ConfigureException(msg);
74 mConfig.mRootPath = path;
77 // TODO: the aim of this constructor is to create a new ContainerImpl based on an already
78 // running container. It should talk to its guard and receive its current config.
79 ContainerImpl::ContainerImpl(pid_t /*guardPid*/)
81 throw NotImplementedException();
84 ContainerImpl::~ContainerImpl()
88 const std::string& ContainerImpl::getName() const
93 const std::string& ContainerImpl::getRootPath() const
95 return mConfig.mRootPath;
98 const std::vector<std::string>& ContainerImpl::getInit()
100 return mConfig.mInit;
103 void ContainerImpl::setInit(const std::vector<std::string> &init)
105 if (init.empty() || init[0].empty()) {
106 const std::string msg = "Init path cannot be empty";
108 throw ConfigureException(msg);
111 std::string path = mConfig.mRootPath + "/" + init[0];
113 if (::access(path.c_str(), X_OK) < 0) {
114 const std::string msg = "Init path must point to an executable file";
116 throw ConfigureException(msg);
119 mConfig.mInit = init;
122 pid_t ContainerImpl::getGuardPid() const
124 return mConfig.mGuardPid;
127 pid_t ContainerImpl::getInitPid() const
129 return mConfig.mInitPid;
132 void ContainerImpl::setLogger(const logger::LogType type,
133 const logger::LogLevel level,
134 const std::string &arg)
136 mConfig.mLogger.set(type, level, arg);
139 void ContainerImpl::setTerminalCount(const unsigned int count)
142 const std::string msg = "Container needs at least one terminal";
144 throw ConfigureException(msg);
147 mConfig.mTerminals.count = count;
150 void ContainerImpl::setNamespaces(const int namespaces)
152 mConfig.mNamespaces = namespaces;
156 int ContainerImpl::getNamespaces() const
158 return mConfig.mNamespaces;
161 void ContainerImpl::start()
163 // TODO: check config consistency and completeness somehow
165 PrepHostTerminal terminal(mConfig.mTerminals);
168 Start start(mConfig);
172 void ContainerImpl::stop()
174 // TODO: things to do when shutting down the container:
175 // - close PTY master FDs from the config so we won't keep PTYs open
181 void ContainerImpl::freeze()
183 throw NotImplementedException();
186 void ContainerImpl::unfreeze()
188 throw NotImplementedException();
191 void ContainerImpl::reboot()
193 throw NotImplementedException();
196 void ContainerImpl::attach(const std::vector<std::string>& argv,
197 const std::string& cwdInContainer)
201 /*uid in container*/ 0,
202 /*gid in container*/ 0,
204 /*supplementary gids in container*/ {},
208 /*envInContainer*/ {{"container","lxcpp"}});
209 // TODO: Env variables should agree with the ones already in the container
213 void ContainerImpl::console()
215 Console console(mConfig.mTerminals);
219 bool ContainerImpl::isRunning() const
221 // TODO: race condition may occur, sync needed
222 return getInitPid() != -1;
225 void ContainerImpl::addInterfaceConfig(const std::string& hostif,
226 const std::string& zoneif,
228 const std::vector<InetAddr>& addrs,
231 mConfig.mNetwork.addInterfaceConfig(hostif, zoneif, type, addrs, mode);
234 void ContainerImpl::addInetConfig(const std::string& ifname, const InetAddr& addr)
236 mConfig.mNetwork.addInetConfig(ifname, addr);
239 std::vector<std::string> ContainerImpl::getInterfaces() const
241 return NetworkInterface::getInterfaces(getInitPid());
244 NetworkInterfaceInfo ContainerImpl::getInterfaceInfo(const std::string& ifname) const
246 NetworkInterface ni(ifname, getInitPid());
247 std::vector<InetAddr> addrs;
249 int mtu = 0, flags = 0;
250 const Attrs& attrs = ni.getAttrs();
251 for (const Attr& a : attrs) {
257 mtu = std::stoul(a.value);
259 case AttrName::FLAGS:
260 flags = std::stoul(a.value);
262 default: //ignore others
266 addrs = ni.getInetAddressList();
267 return NetworkInterfaceInfo{ifname, ni.status(), macaddr, mtu, flags, addrs};
270 void ContainerImpl::createInterface(const std::string& hostif,
271 const std::string& zoneif,
275 NetworkInterface ni(zoneif, getInitPid());
276 ni.create(type, hostif, mode);
279 void ContainerImpl::destroyInterface(const std::string& ifname)
281 NetworkInterface ni(ifname, getInitPid());
285 void ContainerImpl::moveInterface(const std::string& ifname)
287 NetworkInterface ni(ifname);
288 ni.moveToContainer(getInitPid());
291 void ContainerImpl::setUp(const std::string& ifname)
293 NetworkInterface ni(ifname, getInitPid());
297 void ContainerImpl::setDown(const std::string& ifname)
299 NetworkInterface ni(ifname, getInitPid());
303 void ContainerImpl::addInetAddr(const std::string& ifname, const InetAddr& addr)
305 NetworkInterface ni(ifname, getInitPid());
306 ni.addInetAddr(addr);
309 void ContainerImpl::delInetAddr(const std::string& ifname, const InetAddr& addr)
311 NetworkInterface ni(ifname, getInitPid());
312 ni.delInetAddr(addr);
315 void ContainerImpl::declareFile(const provision::File::Type type,
316 const std::string& path,
320 provision::File newFile({type, path, flags, mode});
321 mConfig.mProvisions.addFile(newFile);
322 // TODO: update guard config
325 ProvisionFile fileCmd(mConfig, newFile);
330 const FileVector& ContainerImpl::getFiles() const
332 return mConfig.mProvisions.getFiles();
335 void ContainerImpl::removeFile(const provision::File& item)
337 mConfig.mProvisions.removeFile(item);
340 ProvisionFile fileCmd(mConfig, item);
345 void ContainerImpl::declareMount(const std::string& source,
346 const std::string& target,
347 const std::string& type,
349 const std::string& data)
351 provision::Mount newMount({source, target, type, flags, data});
352 mConfig.mProvisions.addMount(newMount);
353 // TODO: update guard config
356 ProvisionMount mountCmd(mConfig, newMount);
361 const MountVector& ContainerImpl::getMounts() const
363 return mConfig.mProvisions.getMounts();
366 void ContainerImpl::removeMount(const provision::Mount& item)
368 mConfig.mProvisions.removeMount(item);
371 ProvisionMount mountCmd(mConfig, item);
376 void ContainerImpl::declareLink(const std::string& source,
377 const std::string& target)
379 provision::Link newLink({source, target});
380 mConfig.mProvisions.addLink(newLink);
381 // TODO: update guard config
384 ProvisionLink linkCmd(mConfig, newLink);
389 const LinkVector& ContainerImpl::getLinks() const
391 return mConfig.mProvisions.getLinks();
394 void ContainerImpl::removeLink(const provision::Link& item)
396 mConfig.mProvisions.removeLink(item);
399 ProvisionLink linkCmd(mConfig, item);