lxccontainer.c revision f5dd1d532a76a1b57cf341db821eae85ea1118c5
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher/* liblxcapi
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher *
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher * Copyright © 2012 Canonical Ltd.
8c294c1cd4d721818a59684cf7f2b36123f79163Stephen Gallagher *
c252d148fa8ab50aaaa8bbae7beb4d208025171dNikolai Kondrashov * This library is free software; you can redistribute it and/or
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher * modify it under the terms of the GNU Lesser General Public
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher * License as published by the Free Software Foundation; either
9542512d7be40f2000298c86d3d2b728f4f0f65aStephen Gallagher * version 2.1 of the License, or (at your option) any later version.
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov * This library is distributed in the hope that it will be useful,
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov * but WITHOUT ANY WARRANTY; without even the implied warranty of
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c6e39e15178675d0779e0ae855245774a09b4eb5Nikolai Kondrashov * Lesser General Public License for more details.
fd5a4eacd56700ffb08a73121aeacdc806cb0132Sumit Bose
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher * You should have received a copy of the GNU Lesser General Public
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher * License along with this library; if not, write to the Free Software
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher */
8b1f525acd20f36c836e827de3c251088961c5d9Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher#define _GNU_SOURCE
428db8a58c0c149d5efccc6d788f70916c1d34d7Jakub Hrozek#include <stdarg.h>
428db8a58c0c149d5efccc6d788f70916c1d34d7Jakub Hrozek#include <pthread.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <unistd.h>
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include <sys/types.h>
df4cc3a83c5d6700b6a09ff96cb4a6b1949b1aa9Stephen Gallagher#include <sys/wait.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <errno.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <fcntl.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <sched.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <dirent.h>
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "config.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "lxc.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "state.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "lxccontainer.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "conf.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "confile.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "console.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "cgroup.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "commands.h"
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose#include "version.h"
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose#include "log.h"
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose#include "bdev.h"
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose#include "utils.h"
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose#include "attach.h"
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose#include <lxc/utils.h>
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke#include <lxc/monitor.h>
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke#include <lxc/namespace.h>
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke#include <sched.h>
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose#include <arpa/inet.h>
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose#if HAVE_IFADDRS_H
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <ifaddrs.h>
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher#else
2a552e43581c74f51205c7141ec9f6e9542509f8Stephen Gallagher#include <../include/ifaddrs.h>
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek#endif
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifndef HAVE_GETLINE
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#ifdef HAVE_FGETLN
d921c1eba437662437847279f251a0a5d8f70127Maxim#include <../include/getline.h>
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek#endif
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherlxc_log_define(lxc_container, lxc);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool file_exists(char *f)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce struct stat statbuf;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek return stat(f, &statbuf) == 0;
5377441d7a846461c2d9a7a870cea711360a529aNikolai Kondrashov}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void remove_trailing_slashes(char *p)
32381402a4a9afc003782c9e2301fc59c9bda2a9Yassir Elley{
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher int l = strlen(p);
4b6a0d0b3d42e5fdb457f47d9adfa5e66b160256Stephen Gallagher while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
e124844907ed6973915e4d56f5442ecd07535a12Jakub Hrozek p[l] = '\0';
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher/*
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek * A few functions to help detect when a container creation failed.
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek * If a container creation was killed partway through, then trying
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek * to actually start that container could harm the host. We detect
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek * this by creating a 'partial' file under the container directory,
bc13c352ba9c2877f1e9bc62e55ad60fc000a55dJakub Hrozek * and keeping an advisory lock. When container creation completes,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * we remove that file. When we load or try to start a container, if
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * we find that file, without a flock, we remove the container.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint ongoing_create(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int len = strlen(c->config_path) + strlen(c->name) + 10;
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik char *path = alloca(len);
054b5d4bb98973698f74d66b14ccd14394b53f10Lukas Slebodnik int fd, ret;
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek struct flock lk;
a3d176d116ceccd6a7547c128fab5df5cdd2c2b6Michal Zidek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 || ret >= len) {
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik ERROR("Error writing partial pathname");
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
558998ce664055a75595371118f818084d8f2b23Jan Cholasta if (!file_exists(path))
558998ce664055a75595371118f818084d8f2b23Jan Cholasta return 0;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta if (process_lock())
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta return -1;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta if ((fd = open(path, O_RDWR)) < 0) {
558998ce664055a75595371118f818084d8f2b23Jan Cholasta // give benefit of the doubt
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Error opening partial file");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lk.l_type = F_WRLCK;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lk.l_whence = SEEK_SET;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lk.l_start = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lk.l_len = 0;
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny lk.l_pid = -1;
f1828234a850dd28465425248a83a993f262918fPavel Březina if (fcntl(fd, F_GETLK, &lk) == 0 && lk.l_pid != -1) {
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay // create is still ongoing
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay close(fd);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // create completed but partial is still there.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(fd);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 2;
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek}
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozekint create_partial(struct lxc_container *c)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina{
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina // $lxcpath + '/' + $name + '/partial' + \0
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina int len = strlen(c->config_path) + strlen(c->name) + 10;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek char *path = alloca(len);
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek int fd, ret;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek struct flock lk;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name);
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta if (ret < 0 || ret >= len) {
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek ERROR("Error writing partial pathname");
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek return -1;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
19d3aba12c70528708be9440aca66038a291f29eYassir Elley if (process_lock())
19d3aba12c70528708be9440aca66038a291f29eYassir Elley return -1;
19d3aba12c70528708be9440aca66038a291f29eYassir Elley if ((fd=open(path, O_RDWR | O_CREAT | O_EXCL, 0755)) < 0) {
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek SYSERROR("Erorr creating partial file");
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek process_unlock();
f3a25949de81f80c136bb073e4a8f504b080c20cJakub Hrozek return -1;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lk.l_type = F_WRLCK;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose lk.l_whence = SEEK_SET;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose lk.l_start = 0;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose lk.l_len = 0;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (fcntl(fd, F_SETLKW, &lk) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Error locking partial file %s", path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(fd);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return fd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghervoid remove_partial(struct lxc_container *c, int fd)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // $lxcpath + '/' + $name + '/partial' + \0
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int len = strlen(c->config_path) + strlen(c->name) + 10;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher char *path = alloca(len);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher close(fd);
fe60346714a73ac3987f786731389320633dd245Pavel Březina ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (ret < 0 || ret >= len) {
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose ERROR("Error writing partial pathname");
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter return;
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek }
e5e8252ec48bfdd4e7529debc705c8e090264b9aSumit Bose if (process_lock())
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina return;
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher if (unlink(path) < 0)
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina SYSERROR("Error unlink partial file %s", path);
71e7918be3ca5d38794a16a17f6b4f19a24d51fcPavel Březina process_unlock();
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina/* LOCKING
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina * 1. container_mem_lock(c) protects the struct lxc_container from multiple threads.
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina * 2. container_disk_lock(c) protects the on-disk container data - in particular the
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina * container configuration file.
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * The container_disk_lock also takes the container_mem_lock.
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * 3. thread_mutex protects process data (ex: fd table) from multiple threads.
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * NOTHING mutexes two independent programs with their own struct
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * lxc_container for the same c->name, between API calls. For instance,
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * c->config_read(); c->start(); Between those calls, data on disk
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * could change (which shouldn't bother the caller unless for instance
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek * the rootfs get moved). c->config_read(); update; c->config_write();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * Two such updaters could race. The callers should therefore check their
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek * results. Trying to prevent that would necessarily expose us to deadlocks
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek * due to hung callers. So I prefer to keep the locks only within our own
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh * functions, not across functions.
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh *
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose * If you're going to clone while holding a lxccontainer, increment
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha * c->numthreads (under privlock) before forking. When deleting,
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha * decrement numthreads under privlock, then if it hits 0 you can delete.
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek * Do not ever use a lxccontainer whose numthreads you did not bump.
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek */
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březinastatic void lxc_container_free(struct lxc_container *c)
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose{
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose if (!c)
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek return;
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek if (c->configfile) {
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek free(c->configfile);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek c->configfile = NULL;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina }
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek if (c->error_string) {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek free(c->error_string);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose c->error_string = NULL;
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina }
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (c->slock) {
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose lxc_putlock(c->slock);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek c->slock = NULL;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina if (c->privlock) {
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek lxc_putlock(c->privlock);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek c->privlock = NULL;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek }
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek if (c->name) {
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek free(c->name);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek c->name = NULL;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek }
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (c->lxc_conf) {
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek lxc_conf_free(c->lxc_conf);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek c->lxc_conf = NULL;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik }
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik if (c->config_path) {
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik free(c->config_path);
99f8be128274eba264ea1434a7eb2800bced5902Lukas Slebodnik c->config_path = NULL;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik }
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik free(c);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek}
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/*
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * Consider the following case:
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekfreer | racing get()er
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek==================================================================
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherlxc_container_put() | lxc_container_get()
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher\ lxclock(c->privlock) | c->numthreads < 1? (no)
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek\ c->numthreads = 0 | \ lxclock(c->privlock) -> waits
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek\ lxcunlock() | \
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek\ lxc_container_free() | \ lxclock() returns
9f521c61c17cecd9625ebc1b33c666fa3488622cJakub Hrozek | \ c->numthreads < 1 -> return 0
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher\ \ (free stuff) |
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher\ \ sem_destroy(privlock) |
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * When the get()er checks numthreads the first time, one of the following
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * is true:
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * 1. freer has set numthreads = 0. get() returns 0
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * 2. freer is between lxclock and setting numthreads to 0. get()er will
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * sem_wait on privlock, get lxclock after freer() drops it, then see
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * numthreads is 0 and exit without touching lxclock again..
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * 3. freer has not yet locked privlock. If get()er runs first, then put()er
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik * will see --numthreads = 1 and not call lxc_container_free().
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik*/
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagherint lxc_container_get(struct lxc_container *c)
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher{
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
bf5a808fa92007c325c3996e79694badfab201d4Stephen Gallagher
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek // if someone else has already started freeing the container, don't
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // try to take the lock, which may be invalid
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (c->numthreads < 1)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_mem_lock(c))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (c->numthreads < 1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // bail without trying to unlock, bc the privlock is now probably
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik // in freed memory
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik return 0;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik }
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik c->numthreads++;
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik container_mem_unlock(c);
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik return 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherint lxc_container_put(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_mem_lock(c))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose if (--c->numthreads < 1) {
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose container_mem_unlock(c);
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose lxc_container_free(c);
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose return 1;
8a5e793a0576250da80371e53aa3e7eba15cdb63Sumit Bose }
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose container_mem_unlock(c);
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose return 0;
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose}
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bose
90fd1bbd6035cdab46faa3a695a2fb2be6508b17Sumit Bosestatic bool lxcapi_is_defined(struct lxc_container *c)
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke{
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke struct stat statbuf;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke bool ret = false;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke int statret;
af4ffe1001adcc0a96897e426d26444f07af9aa1Benjamin Franzke
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (!c)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher return false;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_mem_lock(c))
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return false;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (!c->configfile)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik goto out;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik statret = stat(c->configfile, &statbuf);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik if (statret != 0)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik goto out;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik ret = true;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikout:
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik container_mem_unlock(c);
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik return ret;
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik}
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnikstatic const char *lxcapi_state(struct lxc_container *c)
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik{
4a5a18f489f4d19aa0571528a7f0c7a8d35ac83fLukas Slebodnik lxc_state_t s;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher s = lxc_getstate(c->name, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return lxc_state2str(s);
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher}
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher
15b266d9f14dad26da8678a79019749d0f69532eStephen Gallagherstatic bool is_stopped(struct lxc_container *c)
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik{
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik lxc_state_t s;
1467daed400d6c186bd0c99c057c42e764309ff3Stephen Gallagher s = lxc_getstate(c->name, c->config_path);
b97595ae059c69b1960a6e7e56d74660388a683bJan Zeleny return (s == STOPPED);
6a6a821866091e0f722808566c25b951aa346d7cStephen Gallagher}
48d7840cae22c5ff4d786149b0d8ecee7efb8306Lukas Slebodnik
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashovstatic bool lxcapi_is_running(struct lxc_container *c)
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov{
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov const char *s;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov if (!c)
60e51fd2764291df2332f36ff478777627d92b57Sumit Bose return false;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik s = lxcapi_state(c);
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik if (!s || strcmp(s, "STOPPED") == 0)
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek return false;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik return true;
18372712592b30638772afb5b7e15bfca92c2058Lukas Slebodnik}
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozek
51d65c4ad15c2cc23f38fa09dd6efeb15e4f3e86Jakub Hrozekstatic bool lxcapi_freeze(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = lxc_freeze(c->name, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret)
17f08cbd0f909181536b93d6c12c7cd69995f09eSumit Bose return false;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov return true;
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov}
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashovstatic bool lxcapi_unfreeze(struct lxc_container *c)
3ce85a5f5264e7118beb6524e120fd8b53a13da4Nikolai Kondrashov{
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov int ret;
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov if (!c)
6398f22526303343193a18e514602f1af6fb29cbNikolai Kondrashov return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = lxc_unfreeze(c->name, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int lxcapi_console_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ttyfd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ttyfd = lxc_console_getfd(c, ttynum, masterfd);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ttyfd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int stdoutfd, int stderrfd, int escape)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic pid_t lxcapi_init_pid(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose if (!c)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return -1;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return lxc_cmd_get_init_pid(c->name, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
eaaeaa7e00c3d4bfa792cc4d3c6770dc1e28ef0cSumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool load_config_locked(struct lxc_container *c, const char *fname)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c->lxc_conf)
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce c->lxc_conf = lxc_conf_init();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return true;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
0ef783e186ef1c9f60e61a4e8e54c44cb366fdfePavel Březina
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozekstatic bool lxcapi_load_config(struct lxc_container *c, const char *alt_file)
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool ret = false, need_disklock = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int lret;
b3b6189850d50c656d62efbd498789124c033b00Lukas Slebodnik const char *fname;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fname = c->configfile;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (alt_file)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fname = alt_file;
c0f9698cd951b7223f251ff2511c4b22a6e4ba60Jan Zeleny if (!fname)
769347ad4d35d43488eb98f980143495b0db415dStef Walter return false;
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose /*
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina * If we're reading something other than the container's config,
769347ad4d35d43488eb98f980143495b0db415dStef Walter * we only need to lock the in-memory container. If loading the
769347ad4d35d43488eb98f980143495b0db415dStef Walter * container's config file, take the disk lock.
769347ad4d35d43488eb98f980143495b0db415dStef Walter */
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (strcmp(fname, c->configfile) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher need_disklock = true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (need_disklock)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lret = container_disk_lock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lret = container_mem_lock(c);
db78f4c750943fcd4b60bca5f3fdfd6cc5d3d4f8Ondrej Kos if (lret)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek ret = load_config_locked(c, fname);
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (need_disklock)
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek container_disk_unlock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina container_mem_unlock(c);
ca261795ce61c41d7e62217ccb2ee913923040ffPavel Březina return ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void lxcapi_want_daemonize(struct lxc_container *c)
77d165f0629966db65753a3aee84a8b4971673afPavel Březina{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_mem_lock(c)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Error getting mem lock");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->daemonize = 1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher container_mem_unlock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
126c9338cf12a3e4404c36bbe4ec14b18f23537cMaxim
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = lxc_wait(c->name, state, timeout, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ret == 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
4e0404ca1b19830dc0f729e59efd5bbd0a9d6103Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool wait_on_daemonized_start(struct lxc_container *c)
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* we'll probably want to make this timeout configurable? */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int timeout = 5, ret, status;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /*
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * our child is going to fork again, then exit. reap the
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * child
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = wait(&status);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
bfbf5cb0f00c60c0f000f56c282377b13b9a89abSumit Bose DEBUG("failed waiting for first dual-fork child");
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return lxcapi_wait(c, "RUNNING", timeout);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2e6087c6cc903d5164b9a1d5e3d791fd046001d9Jakub Hrozek/*
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * I can't decide if it'd be more convenient for callers if we accept '...',
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * or a null-terminated array (i.e. execl vs execv)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct lxc_conf *conf;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int daemonize = 0;
3a4186ae40d0c3b7be46a4c973166f6048fcfe38Lukas Slebodnik char *default_args[] = {
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce "/sbin/init",
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter '\0',
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher };
1658c567191c35beaddffafdb079abe33248037bLukas Slebodnik
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zeleny /* container exists */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
72e60fd4eabcfbcdbfe01e8c38b94052bc6c2067Jakub Hrozek return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* container has been setup */
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny if (!c->lxc_conf)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher return false;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos if ((ret = ongoing_create(c)) < 0) {
701f13b5c8e27bcbfc79e77ce7c76d9f768a448cLukas Slebodnik ERROR("Error checking for incomplete creation");
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret == 2) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Error: %s creation was not completed", c->name);
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorce c->destroy(c);
5f90993426fa2bdc3b3d994c9e85e0805bb92bbcSimo Sorce return false;
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek } else if (ret == 1) {
7452f1b637276ce582b120f8f5482ae7f3b6bd47Jakub Hrozek ERROR("Error: creation of %s is ongoing", c->name);
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce return false;
2fa8d6655ac37f9bdeb34420000052d921f4a543Michal Zidek }
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* is this app meant to be run through lxcinit, as in lxc-execute? */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (useinit && !argv)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
e850be1ff2e13bba9812c94c3d102c0a0b570820Jakub Hrozek if (container_mem_lock(c))
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conf = c->lxc_conf;
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher daemonize = c->daemonize;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher container_mem_unlock(c);
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher if (useinit) {
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher ret = lxc_execute(c->name, argv, 1, conf, c->config_path);
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce return ret == 0 ? true : false;
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (!argv)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek argv = default_args;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek /*
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek * say, I'm not sure - what locks do we want here? Any?
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina * Is liblxc's locking enough here to protect the on disk
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * container? We don't want to exclude things like lxc_info
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * while container is running...
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (daemonize) {
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina if (!lxc_container_get(c))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek lxc_monitord_spawn(c->config_path);
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozek
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny if (process_lock())
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher pid_t pid = fork();
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta if (pid < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxc_container_put(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (pid != 0) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ret = wait_on_daemonized_start(c);
fa70db6004a099afb7cb55031cd7bacb9e78202ePavel Březina process_unlock();
ac47e8854f3bc404f2a35c6682faf621673d6b32Pavel Březina return ret;
b79e0e50a935d108173ca3062f2afe16103fcb1dPavel Březina }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher process_unlock();
f9961e5f82e0ef474d6492371bfdf9e74e208a99Pavel Březina /* second fork to be reparented by init */
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher pid = fork();
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (pid < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Error doing dual-fork");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
3441d0c2d11aea0c39b009751a1898333c009674Stephen Gallagher if (pid != 0)
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher exit(0);
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (chdir("/")) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Error chdir()ing to /.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(0);
4af1d1869d659fec84c518c26844132fa1df8f64Jakub Hrozek close(1);
e9eeb4302e0e426c6cc1a4e65b95a6f7066e80b9Pavel Březina close(2);
cc84fd46f356c4a36a721ab135a33ec77c93e34dJakub Hrozek open("/dev/zero", O_RDONLY);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher open("/dev/null", O_RDWR);
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher open("/dev/null", O_RDWR);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher setsid();
fae99bfe4bfc8b4a12e9c2a0ad01b3684c22f934Simo Sorce }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
8ca73915a3bf60331468fed6b3b38652c979f95dJakub Hrozekreboot:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher conf->reboot = 0;
213ce2a78b1abe3921d8dc13c949a28130d00aecJan Zeleny ret = lxc_start(c->name, argv, conf, c->config_path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
38e2ec1c757955ab557fd95807afa58042d09482Jan Zeleny if (conf->reboot) {
ad07ed37b6b51ef134d4524edaf2259e19ac984fJan Zeleny INFO("container requested reboot");
1a853121ca2ba8ede6df429ee76942131ffb0f65Jan Zeleny conf->reboot = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto reboot;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose
3a62a99faf8e12965100d0b26fc9e07752bd3e2dStephen Gallagher if (daemonize) {
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta lxc_container_put(c);
65e8f538ad35ba7d86cd9e60a3d86aec34537027Stephen Gallagher exit (ret == 0 ? true : false);
88275cccddf39892e01682b39b02292eb74729bdPavel Březina } else {
a679f0167b646cffdae86546ed77e105576991b0Pavel Březina return (ret == 0 ? true : false);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/*
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta * note there MUST be an ending NULL
4139a7a731f2831963a42b26aac111422be28792Jakub Hrozek */
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagherstatic bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
50fe3d79ab12b795a687b676761bef265701626aStephen Gallagher{
3f32406640d89face5e79244b4d8dab34adb6c7cPavel Březina va_list ap;
17d37aecdf397fcb7a1d0c75adebdb25d7be112ePavel Březina char **inargs = NULL;
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose bool bret = false;
e293fba4f5459f3c2dad254dcc966407d8fc3312Jakub Hrozek
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose /* container exists */
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (!c)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose return false;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer va_start(ap, useinit);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina inargs = lxc_va_arg_list_to_argv(ap, 0, 1);
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik va_end(ap);
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik
462db32918a05097652f8232cd6c8d78a826e63cLukas Slebodnik if (!inargs) {
347f7c4d1e8e83fc7ffcaf9524a67e8b3ad5d7c5Jan Cholasta ERROR("Memory allocation error.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek }
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek /* pass NULL if no arguments were supplied */
3b08dec5ee634f83ee18e1753d5ffe0ac5e3c458Jakub Hrozek bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL);
374bf54785365273b20690bd3792c25a44738041Pavel Březina
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagherout:
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher if (inargs) {
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose char *arg;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose for (arg = *inargs; arg; arg++)
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher free(arg);
374bf54785365273b20690bd3792c25a44738041Pavel Březina free(inargs);
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher }
374bf54785365273b20690bd3792c25a44738041Pavel Březina
374bf54785365273b20690bd3792c25a44738041Pavel Březina return bret;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina}
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březinastatic bool lxcapi_stop(struct lxc_container *c)
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina{
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik int ret;
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek if (!c)
eaa723b4d06b4c1e588df67bef44a84bbfaebf1aLukas Slebodnik return false;
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek ret = lxc_cmd_stop(c->name, c->config_path);
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek return ret == 0;
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek}
77c0d1f6074059dafd2293f9c42ea0f9d60f8aadJakub Hrozek
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher/*
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher * create the standard expected container dir
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher */
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagherstatic bool create_container_dir(struct lxc_container *c)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher char *s;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher int len, ret;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt len = strlen(c->config_path) + strlen(c->name) + 2;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher s = malloc(len);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (!s)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return false;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher ret = snprintf(s, len, "%s/%s", c->config_path, c->name);
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher if (ret < 0 || ret >= len) {
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik free(s);
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik return false;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik }
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik ret = mkdir(s, 0755);
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (ret) {
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik if (errno == EEXIST)
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher ret = 0;
87c07559af5cfcd2752295ef7c425bd3205f426fStephen Gallagher else
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik SYSERROR("failed to create container path for %s\n", c->name);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik }
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik free(s);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik return ret == 0;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik}
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnikstatic const char *lxcapi_get_config_path(struct lxc_container *c);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnikstatic bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik/*
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik * do_bdev_create: thin wrapper around bdev_create(). Like bdev_create(),
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik * it returns a mounted bdev on success, NULL on error.
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik */
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnikstatic struct bdev *do_bdev_create(struct lxc_container *c, const char *type,
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik struct bdev_specs *specs)
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik{
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik char *dest;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik const char *lxcpath = lxcapi_get_config_path(c);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik size_t len;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik struct bdev *bdev;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik int ret;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik /* lxcpath/lxcname/rootfs */
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik len = strlen(c->name) + strlen(lxcpath) + 9;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik dest = alloca(len);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ret = snprintf(dest, len, "%s/%s/rootfs", lxcpath, c->name);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (ret < 0 || ret >= len)
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik return NULL;
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik bdev = bdev_create(dest, type, c->name, specs);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik if (!bdev) {
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik ERROR("Failed to create backing store type %s\n", type);
25d4435998d0446f7699e7ab0874c7a6f610ab58Lukas Slebodnik return NULL;
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher lxcapi_set_config_item(c, "lxc.rootfs", bdev->src);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return bdev;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher}
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
4c11f752e1f10cf5740d53a3206bb795e9e34fe8Jan Zeleny/*
c2352a73f52f600d95966ebe0b0819649ba923faStephen Gallagher * Given the '-t' template option to lxc-create, figure out what to
4c1bf6607060cea867fccf667063c028dfd51e96Stephen Gallagher * do. If the template is a full executable path, use that. If it
1f1e6cbc59868f06dee3ab4b3df660fcb77ce1c8Jakub Hrozek * is something like 'sshd', then return $templatepath/lxc-sshd. If
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * no template was passed in, return NULL (this is ok).
2ef62c64e7f07c8aced3f72850008ecb72860162Sumit Bose * On error return (char *) -1.
386a66b1aa18a176e6a06fa126556c9590c373b6Sumit Bose */
817b1bcafff27cc67630dd0cbd36df708c05fcccStephen Gallagherchar *get_template_path(const char *t)
64074e584a56611d7563667e0fcdadd215b0c922Yassir Elley{
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher int ret, len;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher char *tpath;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!t)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return NULL;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (t[0] == '/' && access(t, X_OK) == 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter tpath = strdup(t);
d87e960c17d7598781cf032d06ba03a3ecadbfa2Pavel Březina if (!tpath)
42c28b9424b6ef8a0021b124773e171dd5defaddJakub Hrozek return (char *) -1;
df4e1db5d41c903ae57fd880acc76a0ad84aa7b2Pavel Březina return tpath;
1319e71fd1680ca4864afe0b1aca2b8c8e4a1ee4Stef Walter }
d9577dbd92555b0755881e37724019ef9c578404Stef Walter
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher tpath = malloc(len);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!tpath)
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter return (char *) -1;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (ret < 0 || ret >= len) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher free(tpath);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return (char *) -1;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (access(tpath, X_OK) < 0) {
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher SYSERROR("bad template: %s\n", t);
29be7d76c949b82350c7603cfd362a1fcb47eb1bJan Zeleny free(tpath);
dbea04f585a30d001b574317c068cd03a4fa332bJakub Hrozek return (char *) -1;
5a70b84cb66fb8c7a3fce0e3f2e4b61e0b2ea9d4Simo Sorce }
823a5b3f4375f12b6edae4dd5169ee01771baebeJan Zeleny
9959c512ac3ba36f7a0db7614f0357ce0bae748fJakub Hrozek return tpath;
918b2a5a91f1c551d48f4bffed2a28c36fdb4be1Simo Sorce}
20d0bc6d587f346238062df4da5edfde815e59b1Jan Zeleny
0a55f903a1da319338fdcf147efa01ed22f9710dMichal Zidekstatic char *lxcbasename(char *path)
8bcabb97d988d1602882a1f036aac2eaf5e09234Simo Sorce{
22d381367c27910fe82f476a76b9f4ede555e35aLukas Slebodnik char *p = path + strlen(path) - 1;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik while (*p != '/' && p > path)
7de6e3534fd61c7619ed34a6b1afe7230b5e6504Ondrej Kos p--;
a473fb88e6015cf0ccbd2e9005c7e6acca18f452Pavel Březina return p;
de38d860e39585486e3ccbb42555196e319c7efdSumit Bose}
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnikstatic bool create_run_template(struct lxc_container *c, char *tpath, bool quiet,
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek char *const argv[])
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik{
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik pid_t pid;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek if (!tpath)
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek return true;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher pid = fork();
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik if (pid < 0) {
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek SYSERROR("failed to fork task for container creation template\n");
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik return false;
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik }
5a05b6127064c74349f1edae32e5e13032c386feLukas Slebodnik
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek if (pid == 0) { // child
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek char *patharg, *namearg, *rootfsarg, *src;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek struct bdev *bdev = NULL;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek int i;
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta int ret, len, nargs = 0;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta char **newargv;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta if (quiet) {
1a7d1977037864e52858058777af8ff8401547ddJan Cholasta close(0);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher close(1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(2);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek open("/dev/zero", O_RDONLY);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek open("/dev/null", O_RDWR);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek open("/dev/null", O_RDWR);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek }
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (unshare(CLONE_NEWNS) < 0) {
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek ERROR("error unsharing mounts");
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek exit(1);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek }
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek src = c->lxc_conf->rootfs.path;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek /*
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek * for an overlayfs create, what the user wants is the template to fill
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek * in what will become the readonly lower layer. So don't mount for
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek * the template
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik */
fd98a28d6e94080e52bbedc789b06606a6019b10Lukas Slebodnik if (strncmp(src, "overlayfs:", 10) == 0) {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik src = overlayfs_getlower(src+10);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek bdev = bdev_init(src, c->lxc_conf->rootfs.mount, NULL);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek if (!bdev) {
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik ERROR("Error opening rootfs");
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina exit(1);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina if (bdev->ops->mount(bdev) < 0) {
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina ERROR("Error mounting rootfs");
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina exit(1);
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina }
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina /*
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina * create our new array, pre-pend the template name and
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina * base args
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina */
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina if (argv)
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina for (nargs = 0; argv[nargs]; nargs++) ;
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina nargs += 4; // template, path, rootfs and name args
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina newargv = malloc(nargs * sizeof(*newargv));
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina if (!newargv)
3fc158e59eebbc2f538fe0076a03928d0d4eab9fPavel Březina exit(1);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose newargv[0] = lxcbasename(tpath);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose len = strlen(c->config_path) + strlen(c->name) + strlen("--path=") + 2;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose patharg = malloc(len);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (!patharg)
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik exit(1);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik ret = snprintf(patharg, len, "--path=%s/%s", c->config_path, c->name);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (ret < 0 || ret >= len)
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher exit(1);
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher newargv[1] = patharg;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt len = strlen("--name=") + strlen(c->name) + 1;
b32159300fea63222d8dd9200ed634087704ea74Stephen Gallagher namearg = malloc(len);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (!namearg)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik exit(1);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt ret = snprintf(namearg, len, "--name=%s", c->name);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (ret < 0 || ret >= len)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik exit(1);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik newargv[2] = namearg;
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik len = strlen("--rootfs=") + 1 + strlen(bdev->dest);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose rootfsarg = malloc(len);
b6dfbf81c61d4431aaa81687ec53e892f8b71edbSumit Bose if (!rootfsarg)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek exit(1);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek ret = snprintf(rootfsarg, len, "--rootfs=%s", bdev->dest);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (ret < 0 || ret >= len)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik exit(1);
034ffb3c69cd04f03b36b89766c47a7c9bd9b831Sumit Bose newargv[3] = rootfsarg;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /* add passed-in args */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (argv)
4f6931e854c698dcb1c09f99eb330ce2fb97e7c6Lukas Slebodnik for (i = 4; i < nargs; i++)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik newargv[i] = argv[i-4];
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose /* add trailing NULL */
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose nargs++;
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose newargv = realloc(newargv, nargs * sizeof(*newargv));
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (!newargv)
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt exit(1);
2a9af1f71887f02935e2fb6ad5023afba5b6d43eSumit Bose newargv[nargs - 1] = NULL;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik
0d01e4f6cc21d8ca0e4fafe59c7cbfa1459fa47eSumit Bose /* execute */
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose execv(tpath, newargv);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik SYSERROR("failed to execute template %s", tpath);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik exit(1);
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose }
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose if (wait_for_pid(pid) != 0) {
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose ERROR("container creation template for %s failed\n", c->name);
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose return false;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose }
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose return true;
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose}
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bosebool prepend_lxc_header(char *path, const char *t, char *const argv[])
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose{
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose long flen;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose char *contents;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose FILE *f;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose#if HAVE_LIBGNUTLS
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose int i, ret;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose unsigned char md_value[SHA_DIGEST_LENGTH];
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose char *tpath;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose bool have_tpath = false;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose#endif
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if ((f = fopen(path, "r")) == NULL) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose SYSERROR("Opening old config");
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose return false;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose }
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if (fseek(f, 0, SEEK_END) < 0) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose SYSERROR("Seeking to end of old config file");
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose fclose(f);
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose return false;
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose }
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose if ((flen = ftell(f)) < 0) {
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose SYSERROR("telling size of old config");
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose fclose(f);
f3c85d900c4663854cc7bbae7d9f77867ed1f69bSumit Bose return false;
a9c287bda3fc2a1e12cef2135ade96945f11ad01Sumit Bose }
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (fseek(f, 0, SEEK_SET) < 0) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina SYSERROR("rewinding old config");
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina fclose(f);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina return false;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina if ((contents = malloc(flen + 1)) == NULL) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina SYSERROR("out of memory");
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina fclose(f);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina return false;
0bb98b7700b1b61f5b0a20b93279d5c2c391007fPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina if (fread(contents, 1, flen, f) != flen) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina SYSERROR("Reading old config");
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina free(contents);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina fclose(f);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina return false;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina contents[flen] = '\0';
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina if (fclose(f) < 0) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina SYSERROR("closing old config");
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina free(contents);
706d211b5d6e32d11a1c6ffc8065ca8be4d4d8c5Pavel Březina return false;
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina }
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina#if HAVE_LIBGNUTLS
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina tpath = get_template_path(t);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina if (tpath == (char *) -1) {
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina ERROR("bad template: %s\n", t);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina free(contents);
a7e27c11866a48742bb70564b88e15bf15e9367dPavel Březina return false;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (tpath) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter have_tpath = true;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ret = sha1sum_file(tpath, md_value);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (ret < 0) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter ERROR("Error getting sha1sum of %s", tpath);
769347ad4d35d43488eb98f980143495b0db415dStef Walter free(contents);
769347ad4d35d43488eb98f980143495b0db415dStef Walter return false;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek }
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek free(tpath);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#endif
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if ((f = fopen(path, "w")) == NULL) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter SYSERROR("reopening config for writing");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter free(contents);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return false;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "# Template used to create this container: %s\n", t);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (argv) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "# Parameters passed to the template:");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter while (*argv) {
fcd8093c58638dc7c4f9cddfc97f273b94ce2eadStef Walter fprintf(f, " %s", *argv);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter argv++;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "\n");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter }
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter#if HAVE_LIBGNUTLS
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (have_tpath) {
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "# Template script checksum (SHA-1): ");
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter for (i=0; i<SHA_DIGEST_LENGTH; i++)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "%02x", md_value[i]);
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter fprintf(f, "\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#endif
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fwrite(contents, 1, flen, f) != flen) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Writing original contents");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(contents);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fclose(f);
574a1c20f114851071ae74112b34488c3d1aeeb3Ondrej Kos return false;
769347ad4d35d43488eb98f980143495b0db415dStef Walter }
769347ad4d35d43488eb98f980143495b0db415dStef Walter free(contents);
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (fclose(f) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Closing config file after write");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
9917c138d9a270deb5820915384fbde751190c2aLukas Slebodnik }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return true;
e369fc08906383e6d5c39832f31bb6600a33f887Simo Sorce}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_destroy(struct lxc_container *c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/*
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * lxcapi_create:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * create a container with the given parameters.
ef39c0adcb61b16f9edc7beb4cdc8f3b0d5a8f15Stephen Gallagher * @c: container to be created. It has the lxcpath, name, and a starting
8c3a4809b3420657289b42f028a1c9019b112991Stephen Gallagher * configuration already set
eb2e21b764d03544d8161e9956d7f70b07b75f77Simo Sorce * @t: the template to execute to instantiate the root filesystem and
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * adjust the configuration.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * @bdevtype: backing store type to use. If NULL, dir will be used.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * @specs: additional parameters for the backing store, i.e. LVM vg to
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher * use.
f427b36b0cecc426856ab3f77a9c684ac355659dSumit Bose *
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik * @argv: the arguments to pass to the template, terminated by NULL. If no
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher * arguments, you can just pass NULL.
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_create(struct lxc_container *c, const char *t,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher const char *bdevtype, struct bdev_specs *specs, int flags,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char *const argv[])
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
d844aab866ae237844360cea70e2dccdc90c783dStephen Gallagher bool bret = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pid_t pid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char *tpath;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int partial_fd;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
300c772767c1b12077cac1d148ac89738b058f97Jan Zeleny if (!c)
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek return false;
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek
bdc2aced1185c4ee36921fa01b8dc01789a63900Jakub Hrozek tpath = get_template_path(t);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (tpath == (char *) -1) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ERROR("bad template: %s\n", t);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina goto out;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (!c->save_config(c, NULL)) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ERROR("failed to save starting configuration for %s\n", c->name);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina goto out;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina }
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* container is already created if we have a config and rootfs.path is accessible */
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) == 0)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina goto out;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* Mark that this container is being created */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek if ((partial_fd = create_partial(c)) < 0)
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek goto out;
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /* no need to get disk lock bc we have the partial locked */
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek /*
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * Create the backing store
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik * Note we can't do this in the same task as we use to execute the
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * template because of the way zfs works.
9e80079370ff3b943832adc3c5ef430e64be0a0cJakub Hrozek * After you 'zfs create', zfs mounts the fs only in the initial
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta * namespace.
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta */
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta pid = fork();
b42b5d5aaf4da165582e73ad985fdff6e34e61e4Jakub Hrozek if (pid < 0) {
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta SYSERROR("failed to fork task for container creation template\n");
bd03e67c9d2fc4ad0275e7a573385ee5b7b9307aJan Cholasta goto out_unlock;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta }
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (pid == 0) { // child
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta struct bdev *bdev = NULL;
e7311aec8d691e5427317442387af1bc8fff3742Jan Cholasta
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (!(bdev = do_bdev_create(c, bdevtype, specs))) {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose ERROR("Error creating backing store type %s for %s",
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose bdevtype ? bdevtype : "(none)", c->name);
e3f0014bb64b7e93979948936cf93cf869d3dc44Jan Zeleny exit(1);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose /* save config file again to store the new rootfs location */
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose if (!c->save_config(c, NULL)) {
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose ERROR("failed to save starting configuration for %s\n", c->name);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose // parent task won't see bdev in config so we delete it
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose bdev->ops->umount(bdev);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose bdev->ops->destroy(bdev);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose exit(1);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik exit(0);
b9e5bd09a5ff7009537a18914dbebcf10498f592Sumit Bose }
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if (wait_for_pid(pid) != 0)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek goto out_unlock;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek /* reload config to get the rootfs */
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek if (c->lxc_conf)
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek lxc_conf_free(c->lxc_conf);
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina c->lxc_conf = NULL;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (!load_config_locked(c, c->configfile))
590582be38cdbfde387fcc57df92903d48c5a083Jakub Hrozek goto out_unlock;
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if (!create_run_template(c, tpath, !!(flags & LXC_CREATE_QUIET), argv))
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek goto out_unlock;
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek // now clear out the lxc_conf we have, reload from the created
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek // container
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if (c->lxc_conf)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek lxc_conf_free(c->lxc_conf);
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek c->lxc_conf = NULL;
8214510f125879c3b1d247f2ce981ee20b5375d1Jakub Hrozek
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek if (!prepend_lxc_header(c->configfile, tpath, argv)) {
1a59af8245f183f22d87d067a90197d8e2ea958dJakub Hrozek ERROR("Error prepending header to configuration file");
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina goto out_unlock;
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina }
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina bret = load_config_locked(c, c->configfile);
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březina
8a1fd0633e85221da1fb63451516a70d66c0af31Pavel Březinaout_unlock:
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek if (partial_fd >= 0)
cb4d5b588e704114b7090678752d33512baa718eJakub Hrozek remove_partial(c, partial_fd);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherout:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (tpath)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(tpath);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!bret && c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxcapi_destroy(c);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return bret;
ac47e8854f3bc404f2a35c6682faf621673d6b32Pavel Březina}
b79e0e50a935d108173ca3062f2afe16103fcb1dPavel Březina
769347ad4d35d43488eb98f980143495b0db415dStef Walterstatic bool lxcapi_reboot(struct lxc_container *c)
769347ad4d35d43488eb98f980143495b0db415dStef Walter{
769347ad4d35d43488eb98f980143495b0db415dStef Walter pid_t pid;
769347ad4d35d43488eb98f980143495b0db415dStef Walter
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!c)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return false;
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik if (!c->is_running(c))
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return false;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher pid = c->init_pid(c);
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce if (pid <= 0)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (kill(pid, SIGINT) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
2db6afe70eee2bbc22aa657a6b6609a9f3eb5d4cSimo Sorce return true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek}
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
52e0894fd65bff4715c88330eb62b28e1635228fStephen Gallagherstatic bool lxcapi_shutdown(struct lxc_container *c, int timeout)
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher{
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek bool retv;
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek pid_t pid;
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek
530ba03ecabb472f17d5d1ab546aec9390492de1Jakub Hrozek if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
8a07521b413a3b5879f824e1872c5770c92ee5c0Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!timeout)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher timeout = -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c->is_running(c))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher pid = c->init_pid(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (pid <= 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher kill(pid, SIGPWR);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher retv = c->wait(c, "STOPPED", timeout);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!retv && timeout > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->stop(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher retv = c->wait(c, "STOPPED", 0); // 0 means don't wait
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return retv;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidekstatic bool lxcapi_createl(struct lxc_container *c, const char *t,
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek const char *bdevtype, struct bdev_specs *specs, int flags, ...)
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool bret = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char **args = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher va_list ap;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek /*
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek * since we're going to wait for create to finish, I don't think we
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek * need to get a copy of the arguments.
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce */
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik va_start(ap, flags);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher args = lxc_va_arg_list_to_argv(ap, 0, 0);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher va_end(ap);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!args) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Memory allocation error.");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bret = c->create(c, t, bdevtype, specs, flags, args);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherout:
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek free(args);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return bret;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik}
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
a9eff330a7fbd231e8cc28a6828a1e5014ddb0d2Michal Zidekstatic bool lxcapi_clear_config_item(struct lxc_container *c, const char *key)
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c || !c->lxc_conf)
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_mem_lock(c))
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt ret = lxc_clear_config_item(c->lxc_conf, key);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek container_mem_unlock(c);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek return ret == 0;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek}
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherchar** lxcapi_get_ips(struct lxc_container *c, char* interface, char* family, int scope)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int count = 0;
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char addressOutputBuffer[INET6_ADDRSTRLEN];
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik void *tempAddrPtr = NULL;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt char **addresses = NULL, **temp;
2c0a971010596c122d7a0c0d76c8eb85f16f6d06Jakub Hrozek char *address = NULL;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt char new_netns_path[MAXPATHLEN];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int old_netns = -1, new_netns = -1, ret = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c->is_running(c))
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* Save reference to old netns */
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik old_netns = open("/proc/self/ns/net", O_RDONLY);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (old_netns < 0) {
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny SYSERROR("failed to open /proc/self/ns/net");
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny goto out;
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek }
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* Switch to new netns */
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt ret = snprintf(new_netns_path, MAXPATHLEN, "/proc/%d/ns/net", c->init_pid(c));
543676afec3c08fdc0a5a794976adc8dfdca974bJakub Hrozek if (ret < 0 || ret >= MAXPATHLEN)
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt goto out;
c737e1444fb186e349e59bfa9dac4995b720b4b1Jan Zeleny
f1828234a850dd28465425248a83a993f262918fPavel Březina new_netns = open(new_netns_path, O_RDONLY);
f1828234a850dd28465425248a83a993f262918fPavel Březina if (new_netns < 0) {
f1828234a850dd28465425248a83a993f262918fPavel Březina SYSERROR("failed to open %s", new_netns_path);
f1828234a850dd28465425248a83a993f262918fPavel Březina goto out;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
f1828234a850dd28465425248a83a993f262918fPavel Březina if (setns(new_netns, CLONE_NEWNET)) {
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay SYSERROR("failed to setns");
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay goto out;
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay }
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik /* Grab the list of interfaces */
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (getifaddrs(&interfaceArray)) {
6ea6ec5cb7d9985e2730fb9d4657624d10aed4d8Nick Guay SYSERROR("failed to get interfaces list");
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek goto out;
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek }
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek /* Iterate through the interfaces */
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if(tempIfAddr->ifa_addr->sa_family == AF_INET) {
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek if (family && strcmp(family, "inet"))
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek continue;
1746e8b8399da2a7a8da4aace186f66055ccfec1Jakub Hrozek tempAddrPtr = &((struct sockaddr_in *)tempIfAddr->ifa_addr)->sin_addr;
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina }
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina else {
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina if (family && strcmp(family, "inet6"))
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina continue;
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek if (((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_scope_id != scope)
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina continue;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina tempAddrPtr = &((struct sockaddr_in6 *)tempIfAddr->ifa_addr)->sin6_addr;
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina }
558998ce664055a75595371118f818084d8f2b23Jan Cholasta
558998ce664055a75595371118f818084d8f2b23Jan Cholasta if (interface && strcmp(interface, tempIfAddr->ifa_name))
558998ce664055a75595371118f818084d8f2b23Jan Cholasta continue;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta else if (!interface && strcmp("lo", tempIfAddr->ifa_name) == 0)
558998ce664055a75595371118f818084d8f2b23Jan Cholasta continue;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta
558998ce664055a75595371118f818084d8f2b23Jan Cholasta address = (char *)inet_ntop(tempIfAddr->ifa_addr->sa_family,
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt tempAddrPtr,
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt addressOutputBuffer,
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta sizeof(addressOutputBuffer));
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta if (!address)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta continue;
748ba184db97b7534254f97018fa04e8aa458faeJan Cholasta
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta count += 1;
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta temp = realloc(addresses, count * sizeof(*addresses));
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta if (!temp) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt count--;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt goto out;
558998ce664055a75595371118f818084d8f2b23Jan Cholasta }
558998ce664055a75595371118f818084d8f2b23Jan Cholasta addresses = temp;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher addresses[count - 1] = strdup(address);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashovout:
6e973aa578a692b2e7597811dfdfdb1a442c85f8Nikolai Kondrashov if(interfaceArray)
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose freeifaddrs(interfaceArray);
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose
87d3b47abba6a40fcf809c85a2b138bc1013d9c5Jakub Hrozek /* Switch back to original netns */
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose if (old_netns >= 0 && setns(old_netns, CLONE_NEWNET))
21f28bdbab10881b9fb0b890dfa15af429326606Sumit Bose SYSERROR("failed to setns");
f74d7744f1b12fe0492eadfc8cf30afcb4092e40Lukas Slebodnik if (new_netns >= 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(new_netns);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (old_netns >= 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher close(old_netns);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik /* Append NULL to the array */
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik if (count) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher count++;
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik temp = realloc(addresses, count * sizeof(*addresses));
25c394fc9d09aa7f58700e67b942aba86505934aLukas Slebodnik if (!temp) {
25c394fc9d09aa7f58700e67b942aba86505934aLukas Slebodnik int i;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = 0; i < count-1; i++)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(addresses[i]);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(addresses);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
f74d7744f1b12fe0492eadfc8cf30afcb4092e40Lukas Slebodnik addresses = temp;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik addresses[count - 1] = NULL;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik }
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce return addresses;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce}
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcestatic int lxcapi_get_config_item(struct lxc_container *c, const char *key, char *retv, int inlen)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce{
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce int ret;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce if (!c || !c->lxc_conf)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce return -1;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce if (container_mem_lock(c))
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce return -1;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce ret = lxc_get_config_item(c->lxc_conf, key, retv, inlen);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce container_mem_unlock(c);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce return ret;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce}
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcestatic int lxcapi_get_keys(struct lxc_container *c, const char *key, char *retv, int inlen)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce{
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce if (!key)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik return lxc_listconfigs(retv, inlen);
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik /*
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik * Support 'lxc.network.<idx>', i.e. 'lxc.network.0'
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik * This is an intelligent result to show which keys are valid given
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik * the type of nic it is
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik */
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (!c || !c->lxc_conf)
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik return -1;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (container_mem_lock(c))
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik return -1;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce int ret = -1;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce if (strncmp(key, "lxc.network.", 12) == 0)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce ret = lxc_list_nicconfigs(c->lxc_conf, key, retv, inlen);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce container_mem_unlock(c);
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce return ret;
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce}
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorcestatic bool lxcapi_save_config(struct lxc_container *c, const char *alt_file)
36ccdecd053a9ad88dce86b8c84770dc2aa11d21Simo Sorce{
16c351625346b3193e1762027e5215ab76042127Sumit Bose FILE *fout;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool ret = false, need_disklock = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int lret;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!alt_file)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher alt_file = c->configfile;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!alt_file)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false; // should we write to stdout if no file is specified?
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // If we haven't yet loaded a config, load the stock config
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (!c->lxc_conf) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c->load_config(c, LXC_DEFAULT_CONFIG)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Error loading default configuration file %s while saving %s\n", LXC_DEFAULT_CONFIG, c->name);
16c351625346b3193e1762027e5215ab76042127Sumit Bose return false;
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek }
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek }
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek if (!create_container_dir(c))
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek return false;
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek /*
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek * If we're writing to the container's config file, take the
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek * disk lock. Otherwise just take the memlock to protect the
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik * struct lxc_container while we're traversing it.
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek */
25f8fac2489fd209d603acb2b494f7c72968e9bbMichal Zidek if (strcmp(c->configfile, alt_file) == 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher need_disklock = true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (need_disklock)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lret = container_disk_lock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lret = container_mem_lock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (lret)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fout = fopen(alt_file, "w");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!fout)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher write_config(fout, c->lxc_conf);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fclose(fout);
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek ret = true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
5843ad321944a028f6dee7e1fd4f9381c4953d07Sumit Boseout:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (need_disklock)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher container_disk_unlock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher else
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek container_mem_unlock(c);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek return ret;
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool mod_rdep(struct lxc_container *c, bool inc)
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin{
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik char path[MAXPATHLEN];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret, v = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher FILE *f;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool bret = false;
c8b8901b05da9e31dba320f305ec20301e928cfbSumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (container_disk_lock(c))
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 || ret > MAXPATHLEN)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher f = fopen(path, "r");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (f) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = fscanf(f, "%d", &v);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fclose(f);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret != 1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Corrupted file %s", path);
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher v += inc ? 1 : -1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher f = fopen(path, "w");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!f)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fprintf(f, "%d\n", v) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Error writing new snapshots value");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fclose(f);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fclose(f) != 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Error writing to or closing snapshots file");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bret = true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozekout:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher container_disk_unlock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return bret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void strip_newline(char *p)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t len = strlen(p);
22d381367c27910fe82f476a76b9f4ede555e35aLukas Slebodnik if (len < 1)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (p[len-1] == '\n')
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher p[len-1] = '\0';
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void mod_all_rdeps(struct lxc_container *c, bool inc)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina struct lxc_container *p;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char *lxcpath = NULL, *lxcname = NULL, path[MAXPATHLEN];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher size_t pathlen = 0, namelen = 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher FILE *f;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_rdepends",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->config_path, c->name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 || ret >= MAXPATHLEN) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Path name too long");
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if ((f = fopen(path, "r")) == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher while (getline(&lxcpath, &pathlen, f) != -1) {
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (getline(&lxcname, &namelen, f) == -1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("badly formatted file %s\n", path);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher strip_newline(lxcpath);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher strip_newline(lxcname);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if ((p = lxc_container_new(lxcname, lxcpath)) == NULL) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Unable to find dependent container %s:%s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxcpath, lxcname);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher continue;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!mod_rdep(p, inc))
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher ERROR("Failed to increase numsnapshots for %s:%s",
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxcpath, lxcname);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxc_container_put(p);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherout:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (lxcpath) free(lxcpath);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (lxcname) free(lxcname);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik fclose(f);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool has_snapshots(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char path[MAXPATHLEN];
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek int ret, v;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher FILE *f;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool bret = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->name);
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce if (ret < 0 || ret > MAXPATHLEN)
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher f = fopen(path, "r");
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher if (!f)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = fscanf(f, "%d", &v);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fclose(f);
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce if (ret != 1)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bret = v != 0;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagherout:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return bret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher// do we want the api to support --force, or leave that to the caller?
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_destroy(struct lxc_container *c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik struct bdev *r = NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool ret = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c || !lxcapi_is_defined(c))
35872dc24058c5e8028cb4082fd405a27835dcd1Jakub Hrozek return false;
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozek
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozek if (container_disk_lock(c))
fcb8e3f1f49bb34c409d8dbd75889eb72be05517Jakub Hrozek return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!is_stopped(c)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // we should queue some sort of error - in c->error_string?
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("container %s is not stopped", c->name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
c51f7a064b0d7ef86110bdeb6dc09fa6c08be7d3Jakub Hrozek if (c->lxc_conf && has_snapshots(c)) {
d12c95d840ed5de7f34e21002943c48e711a33f4Lukas Slebodnik ERROR("container %s has dependent snapshots", c->name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (c->lxc_conf && c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount)
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher r = bdev_init(c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (r) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher if (r->ops->destroy(r) < 0) {
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher bdev_put(r);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher ERROR("Error destroying rootfs for %s", c->name);
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher goto out;
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher }
effcbdb12c7ef892f1fd92a745cb33a08ca4ba30Stephen Gallagher bdev_put(r);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
d35ff4d0db1cd87c94091a85846b46e4732b1eeePavel Březina mod_all_rdeps(c, false);
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek const char *p1 = lxcapi_get_config_path(c);
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek char *path = alloca(strlen(p1) + strlen(c->name) + 2);
584eda085e83a428f2c39dadf0d7adeaff5c87f4Jakub Hrozek sprintf(path, "%s/%s", p1, c->name);
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek if (lxc_rmdir_onedev(path) < 0) {
0cf0e2d758d09e9b314ba72ce6638df10b258462Pavel Březina ERROR("Error destroying container directory for %s", c->name);
0cf0e2d758d09e9b314ba72ce6638df10b258462Pavel Březina goto out;
769347ad4d35d43488eb98f980143495b0db415dStef Walter }
769347ad4d35d43488eb98f980143495b0db415dStef Walter ret = true;
769347ad4d35d43488eb98f980143495b0db415dStef Walter
769347ad4d35d43488eb98f980143495b0db415dStef Walterout:
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek container_disk_unlock(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozekstatic bool set_config_item_locked(struct lxc_container *c, const char *key, const char *v)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
ccf340e56364851f2e5b75e52d3d63701b662954Lukas Slebodnik struct lxc_config_t *config;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek if (!c->lxc_conf)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher c->lxc_conf = lxc_conf_init();
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek if (!c->lxc_conf)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
c0bca1722d6f9dfb654ad78397be70f79ff39af1Jakub Hrozek config = lxc_getconfig(key);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!config)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher return (0 == config->cb(key, v, c->lxc_conf));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic bool lxcapi_set_config_item(struct lxc_container *c, const char *key, const char *v)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher bool b = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (!c)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter if (container_mem_lock(c))
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter return false;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter b = set_config_item_locked(c, key, v);
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter container_mem_unlock(c);
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter return b;
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter}
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walterstatic char *lxcapi_config_file_name(struct lxc_container *c)
b9d8c6172e48a2633ebe196b2e88bebdf9523c20Stef Walter{
fe60346714a73ac3987f786731389320633dd245Pavel Březina if (!c || !c->configfile)
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina return NULL;
2de495aed26bf75a750a76ca73b9f85d341fe1c5Pavel Březina return strdup(c->configfile);
fe60346714a73ac3987f786731389320633dd245Pavel Březina}
fe60346714a73ac3987f786731389320633dd245Pavel Březina
fe60346714a73ac3987f786731389320633dd245Pavel Březinastatic const char *lxcapi_get_config_path(struct lxc_container *c)
fe60346714a73ac3987f786731389320633dd245Pavel Březina{
fe60346714a73ac3987f786731389320633dd245Pavel Březina if (!c || !c->config_path)
fe60346714a73ac3987f786731389320633dd245Pavel Březina return NULL;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return (const char *)(c->config_path);
fe60346714a73ac3987f786731389320633dd245Pavel Březina}
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek/*
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek * not for export
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek * Just recalculate the c->configfile based on the
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek * c->config_path, which must be set.
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek * The lxc_container must be locked or not yet public.
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek */
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozekstatic bool set_config_filename(struct lxc_container *c)
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher{
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek char *newpath;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek int len, ret;
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek if (!c->config_path)
69aaef8719c5cf33ed1c4090fa313ba281bf8a02Jakub Hrozek return false;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher len = strlen(c->config_path) + strlen(c->name) + strlen("config") + 3;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher newpath = malloc(len);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (!newpath)
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher return false;
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher ret = snprintf(newpath, len, "%s/%s/config", c->config_path, c->name);
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher if (ret < 0 || ret >= len) {
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher fprintf(stderr, "Error printing out config file name\n");
4dd615c01357b8715711aad6820ba9595d3ad377Stephen Gallagher free(newpath);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose return false;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose }
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose if (c->configfile)
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose free(c->configfile);
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose c->configfile = newpath;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose return true;
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose}
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bose
a6098862048d4bb469130b9ff21be3020d6f2c54Sumit Bosestatic bool lxcapi_set_config_path(struct lxc_container *c, const char *path)
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose{
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose char *p;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose bool b = false;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose char *oldpath = NULL;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose if (!c)
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose return b;
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose if (container_mem_lock(c))
2d257ccf620ce1b611f89cec8f0a94c88c2f2881Sumit Bose return b;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik p = strdup(path);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (!p) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Out of memory setting new lxc path");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher b = true;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (c->config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher oldpath = c->config_path;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->config_path = p;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* Since we've changed the config path, we have to change the
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * config file name too */
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek if (!set_config_filename(c)) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek ERROR("Out of memory setting new config filename");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek b = false;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek free(c->config_path);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek c->config_path = oldpath;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek oldpath = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozekerr:
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek if (oldpath)
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek free(oldpath);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek container_mem_unlock(c);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return b;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic bool lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsys, const char *value)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int ret;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (!c)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return false;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (is_stopped(c))
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek return false;
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter if (container_disk_lock(c))
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter return false;
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter ret = lxc_cgroup_set(c->name, subsys, value, c->config_path);
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter container_disk_unlock(c);
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter return ret == 0;
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter}
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walter
f5e47e1d65f80ffdb1893feab18583a74d661214Stef Walterstatic int lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys, char *retv, int inlen)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter{
1203e462650f035b0df2304075d60b9a99e36715Stef Walter int ret;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (!c || !c->lxc_conf)
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (is_stopped(c))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter if (container_disk_lock(c))
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter return -1;
b699c4d7f85a5404be1d1ee9450331aea869b886Stef Walter
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek ret = lxc_cgroup_get(c->name, subsys, retv, inlen, c->config_path);
4bd20c075f0f187db0181dc53d00ab6cd47fdb4dJakub Hrozek
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina container_disk_unlock(c);
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina return ret;
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březinaconst char *lxc_get_default_config_path(void)
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina{
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina return default_lxc_path();
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březinaconst char *lxc_get_default_lvm_vg(void)
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina{
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina return default_lvm_vg();
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina}
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březinaconst char *lxc_get_default_zfs_root(void)
bbaba8b3ef9bc101863b8687f234f4ee956caacdPavel Březina{
80314a6f3ea8d81abe73d501d5b953a256cb2167Pavel Březina return default_zfs_root();
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek}
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozekconst char *lxc_get_version(void)
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek{
c440c424443517b12afa8d56f989d92ca6ba56a3Jakub Hrozek return lxc_version();
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek}
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozekstatic int copy_file(char *old, char *new)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina int in, out;
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek ssize_t len, ret;
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina char buf[8096];
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina struct stat sbuf;
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina if (file_exists(new)) {
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina ERROR("copy destination %s exists", new);
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina return -1;
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina }
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina ret = stat(old, &sbuf);
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina if (ret < 0) {
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina INFO("Error stat'ing %s", old);
dc70b11ddc2dfc6ed99cd895f020cd3429278968Pavel Březina return -1;
16c351625346b3193e1762027e5215ab76042127Sumit Bose }
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek in = open(old, O_RDONLY);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek if (in < 0) {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek SYSERROR("Error opening original file %s", old);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek return -1;
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek }
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek out = open(new, O_CREAT | O_EXCL | O_WRONLY, 0644);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek if (out < 0) {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek SYSERROR("Error opening new file %s", new);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek close(in);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek return -1;
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek }
a044c9a1012d11a2a75e9976ebf186d2d781d291Pallavi Jha
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek while (1) {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek len = read(in, buf, 8096);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek if (len < 0) {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek SYSERROR("Error reading old file %s", old);
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek goto err;
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (len == 0)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik break;
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik ret = write(out, buf, len);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik if (ret < len) { // should we retry?
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh SYSERROR("Error: write to new file %s was interrupted", new);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek goto err;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek }
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek }
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek close(in);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek close(out);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek // we set mode, but not owner/group
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek ret = chmod(new, sbuf.st_mode);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek if (ret) {
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek SYSERROR("Error setting mode on %s", new);
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek return -1;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek }
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek return 0;
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozek
7caf7ed4f2eae1ec1c0717b4ee6ce78bdacd5926Jakub Hrozekerr:
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek close(in);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek close(out);
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek return -1;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek}
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozekstatic int copyhooks(struct lxc_container *oldc, struct lxc_container *c)
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek{
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek int i;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek int ret;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek struct lxc_list *it;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek for (i=0; i<NUM_LXC_HOOKS; i++) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek lxc_list_for_each(it, &c->lxc_conf->hooks[i]) {
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek char *hookname = it->elem;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek char *fname = strrchr(hookname, '/');
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek char tmppath[MAXPATHLEN];
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek if (!fname) // relative path - we don't support, but maybe we should
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek return 0;
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek // copy the script, and change the entry in confile
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek ret = snprintf(tmppath, MAXPATHLEN, "%s/%s/%s",
0161a3c5637a0c0092bf54c436bb3d6508d7df26Jakub Hrozek c->config_path, c->name, fname+1);
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh if (ret < 0 || ret >= MAXPATHLEN)
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh return -1;
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh ret = copy_file(it->elem, tmppath);
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh if (ret < 0)
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh return -1;
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh free(it->elem);
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh it->elem = strdup(tmppath);
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh if (!it->elem) {
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce ERROR("out of memory copying hook path");
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce return -1;
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh }
a65a64aee968bd2ac18156ced15a1e2509a8acbaAbhishek Singh
b49a7d90708e816120ff88ce5a88fa62b35ff795Simo Sorce c->save_config(c, NULL);
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return 0;
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh}
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singhstatic void new_hwaddr(char *hwaddr)
25255e4d0e1517a5d443e8fee22e91862e255702Abhishek Singh{
25255e4d0e1517a5d443e8fee22e91862e255702Abhishek Singh FILE *f = fopen("/dev/urandom", "r");
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh if (f) {
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh unsigned int seed;
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh int ret = fread(&seed, sizeof(seed), 1, f);
ae6c1596225c65bec2a2dabff9eee4e3e0691181Abhishek Singh if (ret != 1)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek seed = time(NULL);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha fclose(f);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha srand(seed);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha } else
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha srand(time(NULL));
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha snprintf(hwaddr, 18, "00:16:3e:%02x:%02x:%02x",
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha rand() % 255, rand() % 255, rand() % 255);
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha}
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jhastatic void network_new_hwaddrs(struct lxc_container *c)
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha{
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha struct lxc_list *it;
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha lxc_list_for_each(it, &c->lxc_conf->network) {
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha struct lxc_netdev *n = it->elem;
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha if (n->hwaddr)
d00ffd2cb4e2f17c75b466178bb645b5c9317909Pallavi Jha new_hwaddr(n->hwaddr);
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha }
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha}
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jhastatic int copy_fstab(struct lxc_container *oldc, struct lxc_container *c)
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha{
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha char newpath[MAXPATHLEN];
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha char *oldpath = oldc->lxc_conf->fstab;
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha int ret;
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha if (!oldpath)
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha return 0;
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha char *p = strrchr(oldpath, '/');
461da2984c747708e8badd27fa55ef879f40e712Pallavi Jha if (!p)
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik return -1;
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik ret = snprintf(newpath, MAXPATHLEN, "%s/%s%s",
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik c->config_path, c->name, p);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik if (ret < 0 || ret >= MAXPATHLEN) {
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik ERROR("error printing new path for %s", oldpath);
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik return -1;
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik }
f28b09f887870c10c8c611beee3c17eaa9ef74f3Lukas Slebodnik if (file_exists(newpath)) {
d65f692d7b7639ed8ba0f5cffa4f88b68056739aLukas Slebodnik ERROR("error: fstab file %s exists", newpath);
16c351625346b3193e1762027e5215ab76042127Sumit Bose return -1;
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (copy_file(oldpath, newpath) < 0) {
04868f1573f4b26ef34610b6d7069172f93bd8abJakub Hrozek ERROR("error: copying %s to %s", oldpath, newpath);
04868f1573f4b26ef34610b6d7069172f93bd8abJakub Hrozek return -1;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek free(c->lxc_conf->fstab);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek c->lxc_conf->fstab = strdup(newpath);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (!c->lxc_conf->fstab) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek ERROR("error: allocating pathname");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return -1;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek }
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return 0;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek}
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnikstatic void copy_rdepends(struct lxc_container *c, struct lxc_container *c0)
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik{
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek char path0[MAXPATHLEN], path1[MAXPATHLEN];
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek int ret;
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek ret = snprintf(path0, MAXPATHLEN, "%s/%s/lxc_rdepends", c0->config_path,
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek c0->name);
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek if (ret < 0 || ret >= MAXPATHLEN) {
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek WARN("Error copying reverse dependencies");
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik return;
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik }
577ba99b3150404533bd3d859522a2c994b17e76Lukas Slebodnik ret = snprintf(path1, MAXPATHLEN, "%s/%s/lxc_rdepends", c->config_path,
777374243e15c53e7b0a7345e190c1018920be18Jakub Hrozek c->name);
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina if (ret < 0 || ret >= MAXPATHLEN) {
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina WARN("Error copying reverse dependencies");
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina return;
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek }
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina if (copy_file(path0, path1) < 0) {
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek INFO("Error copying reverse dependencies");
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek return;
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina }
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek}
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březinastatic bool add_rdepends(struct lxc_container *c, struct lxc_container *c0)
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina{
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina int ret;
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina char path[MAXPATHLEN];
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek FILE *f;
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek bool bret;
8a8618717c99b7331125fa736b45d9155da797d3Jakub Hrozek
e046ae03d0f55b1c8b0ec2fa6139bf86a3449adfPavel Březina ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_rdepends", c->config_path,
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose c->name);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (ret < 0 || ret >= MAXPATHLEN)
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose return false;
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose f = fopen(path, "a");
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (!f)
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose return false;
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik bret = true;
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose // if anything goes wrong, just return an error
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose if (fprintf(f, "%s\n%s\n", c0->config_path, c0->name) < 0)
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose bret = false;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose if (fclose(f) != 0)
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose bret = false;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose return bret;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose}
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose
f69f3581658351003a6d9245045e41d0efb85022Sumit Bosestatic int copy_storage(struct lxc_container *c0, struct lxc_container *c,
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose const char *newtype, int flags, const char *bdevdata, unsigned long newsize)
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose{
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose struct bdev *bdev;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose int need_rdep;
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose
f69f3581658351003a6d9245045e41d0efb85022Sumit Bose bdev = bdev_copy(c0->lxc_conf->rootfs.path, c0->name, c->name,
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose c0->config_path, c->config_path, newtype, !!(flags & LXC_CLONE_SNAPSHOT),
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose bdevdata, newsize, &need_rdep);
d064fef06dcbcb5f6c1be03e286b1a3433d6dfd7Sumit Bose if (!bdev) {
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose ERROR("Error copying storage");
b5f61c9b3f5ea79bf319c18ff59394070c04d607Pavel Reichl return -1;
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik }
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik free(c->lxc_conf->rootfs.path);
022c6b90bb37851c0e8704c0e5388ebc113c6470Lukas Slebodnik c->lxc_conf->rootfs.path = strdup(bdev->src);
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose bdev_put(bdev);
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose if (!c->lxc_conf->rootfs.path) {
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose ERROR("Out of memory while setting storage path");
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose return -1;
221619d8e8d7cf269c55482e5f466f6511ed35adLukas Slebodnik }
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose if (flags & LXC_CLONE_SNAPSHOT)
939246537b0b9a4af6862c513d3919501ad57d92Sumit Bose copy_rdepends(c, c0);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (need_rdep) {
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl if (!add_rdepends(c, c0))
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl WARN("Error adding reverse dependency from %s to %s",
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl c->name, c0->name);
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl }
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl mod_all_rdeps(c, true);
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl return 0;
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl}
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichlstatic int clone_update_rootfs(struct lxc_container *c0,
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl struct lxc_container *c, int flags,
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl char **hookargs)
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl{
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl int ret = -1;
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl char path[MAXPATHLEN];
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl struct bdev *bdev;
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl FILE *fout;
cebdc563a094d305b91da5b5af4d95d8e3a1bf27Pavel Reichl pid_t pid;
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek struct lxc_conf *conf = c->lxc_conf;
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek /* update hostname in rootfs */
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek /* we're going to mount, so run in a clean namespace to simplify cleanup */
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek pid = fork();
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (pid < 0)
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek return -1;
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (pid > 0)
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek return wait_for_pid(pid);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (unshare(CLONE_NEWNS) < 0) {
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek ERROR("error unsharing mounts");
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek exit(1);
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley bdev = bdev_init(c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (!bdev)
0352c371e743d8dae996123f658b5d32c677614eYassir Elley exit(1);
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (bdev->ops->mount(bdev) < 0)
0352c371e743d8dae996123f658b5d32c677614eYassir Elley exit(1);
0352c371e743d8dae996123f658b5d32c677614eYassir Elley
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (!lxc_list_empty(&conf->hooks[LXCHOOK_CLONE])) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley /* Start of environment variable setup for hooks */
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (setenv("LXC_SRC_NAME", c0->name, 1)) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley SYSERROR("failed to set environment variable for source container name");
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (setenv("LXC_NAME", c->name, 1)) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley SYSERROR("failed to set environment variable for container name");
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley SYSERROR("failed to set environment variable for config path");
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) {
0352c371e743d8dae996123f658b5d32c677614eYassir Elley SYSERROR("failed to set environment variable for rootfs mount");
0352c371e743d8dae996123f658b5d32c677614eYassir Elley }
0352c371e743d8dae996123f658b5d32c677614eYassir Elley if (setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) {
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek SYSERROR("failed to set environment variable for rootfs mount");
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek }
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek if (run_lxc_hooks(c->name, "clone", conf, c->get_config_path(c), hookargs)) {
1ce58f139699dd26b8888f4131c996263b6a80a5Jakub Hrozek ERROR("Error executing clone hook for %s", c->name);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(1);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek }
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek }
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (!(flags & LXC_CLONE_KEEPNAME)) {
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek ret = snprintf(path, MAXPATHLEN, "%s/etc/hostname", bdev->dest);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (ret < 0 || ret >= MAXPATHLEN)
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(1);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (!file_exists(path))
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(0);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (!(fout = fopen(path, "w"))) {
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek SYSERROR("unable to open %s: ignoring\n", path);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(0);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek }
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (fprintf(fout, "%s", c->name) < 0)
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(1);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek if (fclose(fout) < 0)
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(1);
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek }
72ae534f5aef6d2e5d3f2f51299aede5abf9687eJakub Hrozek exit(0);
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek}
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek/*
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek * We want to support:
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozeksudo lxc-clone -o o1 -n n1 -s -L|-fssize fssize -v|--vgname vgname \
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek -p|--lvprefix lvprefix -t|--fstype fstype -B backingstore
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek-s [ implies overlayfs]
5c36e1f8901a4baff2b51d81d87c2b577f84fef6Lukas Slebodnik-s -B overlayfs
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek-s -B aufs
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozek
90afedb00608547ae1f32aa7aafd552c4b306909Jakub Hrozekonly rootfs gets converted (copied/snapshotted) on clone.
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek*/
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozekstatic int create_file_dirname(char *path)
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek{
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek char *p = strrchr(path, '/');
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek int ret;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek if (!p)
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek return -1;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek *p = '\0';
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek ret = mkdir(path, 0755);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek if (ret && errno != EEXIST)
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek SYSERROR("creating container path %s\n", path);
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek *p = '/';
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek return ret;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek}
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozekstruct lxc_container *lxcapi_clone(struct lxc_container *c, const char *newname,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek const char *lxcpath, int flags,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek const char *bdevtype, const char *bdevdata, unsigned long newsize,
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek char **hookargs)
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek{
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek struct lxc_container *c2 = NULL;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek char newpath[MAXPATHLEN];
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek int ret, storage_copied = 0;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek const char *n, *l;
842f83f8db513214241a0fea076ac160b180e1ddLukas Slebodnik FILE *fout;
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek if (!c || !c->is_defined(c))
e592d5f157be869151983bd1b46d6f4f7a29daafJakub Hrozek return NULL;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (container_mem_lock(c))
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek return NULL;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (!is_stopped(c)) {
3fe339bcba0e211cc666bb3afe34e5c8fce85f4fJakub Hrozek ERROR("error: Original container (%s) is running", c->name);
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose goto out;
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose }
115de6d50f0d0bdd5745a5d8eb0d067be9128528Sumit Bose
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek // Make sure the container doesn't yet exist.
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek n = newname ? newname : c->name;
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek l = lxcpath ? lxcpath : c->get_config_path(c);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek ret = snprintf(newpath, MAXPATHLEN, "%s/%s/config", l, n);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (ret < 0 || ret >= MAXPATHLEN) {
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek SYSERROR("clone: failed making config pathname");
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek goto out;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina }
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (file_exists(newpath)) {
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina ERROR("error: clone: %s exists", newpath);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina goto out;
0bb98b7700b1b61f5b0a20b93279d5c2c391007fPavel Březina }
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina ret = create_file_dirname(newpath);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (ret < 0 && errno != EEXIST) {
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina ERROR("Error creating container dir for %s", newpath);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina goto out;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina }
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina // copy the configuration, tweak it as needed,
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina fout = fopen(newpath, "w");
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina if (!fout) {
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina SYSERROR("open %s", newpath);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina goto out;
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina }
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina write_config(fout, c->lxc_conf);
efa6c1f75c4c18bcc148d6e7efd429c2d56499adPavel Březina fclose(fout);
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina
f43c6a9ae2aea13b7a83fd932139f9352efbfcadPavel Březina sprintf(newpath, "%s/%s/rootfs", l, n);
770dc892f867639f36f84455d65be6287935a529Jakub Hrozek if (mkdir(newpath, 0755) < 0) {
150b76e13b7c4f3ccf1d709bf517ca2af6b2c9a2Jakub Hrozek SYSERROR("error creating %s", newpath);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose goto out;
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose }
8eb981dd8bc85aee7a913c6f0096ad47f3382339Sumit Bose
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose c2 = lxc_container_new(n, l);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose if (!c2) {
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose ERROR("clone: failed to create new container (%s %s)", n, l);
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose goto out;
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose }
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose // update utsname
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose if (!set_config_item_locked(c2, "lxc.utsname", newname)) {
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose ERROR("Error setting new hostname");
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose goto out;
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose }
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose
a524965fbe0551f1b3a68f1e5c7a5689a652998fSumit Bose
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina // copy hooks if requested
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina if (flags & LXC_CLONE_COPYHOOKS) {
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina ret = copyhooks(c, c2);
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina if (ret < 0) {
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina ERROR("error copying hooks");
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina goto out;
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina }
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina }
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina if (copy_fstab(c, c2) < 0) {
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina ERROR("error copying fstab");
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina goto out;
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina }
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina
a5623363d6042290fe652a1ca5ce5a85a821236fPavel Březina // update macaddrs
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (!(flags & LXC_CLONE_KEEPMACADDR))
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose network_new_hwaddrs(c2);
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose // copy/snapshot rootfs's
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose ret = copy_storage(c, c2, bdevtype, flags, bdevdata, newsize);
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (ret < 0)
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose goto out;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose // We've now successfully created c2's storage, so clear it out if we
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose // fail after this
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose storage_copied = 1;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (!c2->save_config(c2, NULL))
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose goto out;
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose if (clone_update_rootfs(c, c2, flags, hookargs) < 0)
802385896dc1c4e7b8bbd40dcfe3cd131f68e696Sumit Bose goto out;
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose // TODO: update c's lxc.snapshot = count
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose container_mem_unlock(c);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose return c2;
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Boseout:
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose container_mem_unlock(c);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose if (c2) {
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose if (!storage_copied)
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose c2->lxc_conf->rootfs.path = NULL;
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose c2->destroy(c2);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose lxc_container_put(c2);
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose }
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose return NULL;
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose}
a0ab15ceb80290db80c2052520830a95390de385Sumit Bose
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozekstatic int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek{
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek if (!c)
fb3c5cdfcda069a5fbeb7b9d200c0881911364b8Jakub Hrozek return -1;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek}
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozekstatic int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek{
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik lxc_attach_command_t command;
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik pid_t pid;
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik int r;
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik if (!c)
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek return -1;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek command.program = (char*)program;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek command.argv = (char**)argv;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek if (r < 0) {
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek ERROR("ups");
44703b84feaafa4f0a4f8df11c5a503dcf48616eJakub Hrozek return r;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek }
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek return lxc_wait_for_pid_status(pid);
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek}
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnikint get_next_index(const char *lxcpath, char *cname)
4d9db278db1197ae84fecb8f269e2de368a6be2aLukas Slebodnik{
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek char *fname;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek struct stat sb;
e00c2b5ac4963de9521599c88597b7fb97339d0eJakub Hrozek int i = 0, ret;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina fname = alloca(strlen(lxcpath) + 20);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina while (1) {
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina sprintf(fname, "%s/snap%d", lxcpath, i);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina ret = stat(fname, &sb);
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina if (ret != 0)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina return i;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina i++;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina }
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina}
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březinastatic int lxcapi_snapshot(struct lxc_container *c, char *commentfile)
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina{
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina int i, flags, ret;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina struct lxc_container *c2;
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina char snappath[MAXPATHLEN], newname[20];
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina
360a4be4266d6a72be99dfd252623dc0527f5b84Pavel Březina // /var/lib/lxc -> /var/lib/lxcsnaps \0
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina if (ret < 0 || ret >= MAXPATHLEN)
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina return -1;
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina i = get_next_index(snappath, c->name);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina if (mkdir_p(snappath, 0755) < 0) {
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina ERROR("Failed to create snapshot directory %s", snappath);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina return -1;
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina }
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina ret = snprintf(newname, 20, "snap%d", i);
3a8f6b575f4019f21c9425a26f1b346c08a197aePavel Březina if (ret < 0 || ret >= 20)
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek return -1;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek flags = LXC_CLONE_SNAPSHOT | LXC_CLONE_KEEPMACADDR | LXC_CLONE_KEEPNAME;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek c2 = c->clone(c, newname, snappath, flags, NULL, NULL, 0, NULL);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek if (!c2) {
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek ERROR("clone of %s:%s failed\n", c->config_path, c->name);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek return -1;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek }
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek lxc_container_put(c2);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek // Now write down the creation time
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek time_t timer;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek char buffer[25];
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek struct tm* tm_info;
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek time(&timer);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek tm_info = localtime(&timer);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek strftime(buffer, 25, "%Y:%m:%d %H:%M:%S", tm_info);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek char *dfnam = alloca(strlen(snappath) + strlen(newname) + 5);
bf54fbed126ec3d459af40ea370ffadacd31c76dJakub Hrozek sprintf(dfnam, "%s/%s/ts", snappath, newname);
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek FILE *f = fopen(dfnam, "w");
f92ace4a52602e8c38a34f2392bec3deeac2ddddJakub Hrozek if (!f) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Failed to open %s\n", dfnam);
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina return -1;
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina }
f8c829e72968b574e1c9bda96f4d5f206622358fPavel Březina if (fprintf(f, "%s", buffer) < 0) {
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek SYSERROR("Writing timestamp");
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek fclose(f);
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek return -1;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fclose(f) != 0) {
d2d21d45a88d0869f860e215c2cf946f032818caLukas Slebodnik SYSERROR("Writing timestamp");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek }
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher if (commentfile) {
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher // $p / $name / comment \0
8359bf07a2e6c0181251ce8d5d9160dc57546c55Stephen Gallagher int len = strlen(snappath) + strlen(newname) + 10;
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek char *path = alloca(len);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt sprintf(path, "%s/%s/comment", snappath, newname);
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek return copy_file(commentfile, path) < 0 ? -1 : i;
6e8238868a4d17030bb4f01494961d0354a953bfJakub Hrozek }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return i;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic void lxcsnap_free(struct lxc_snapshot *s)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (s->name)
f1ac7d7859b26f0f36f5e8ffacda609f8ece80e5Stephen Gallagher free(s->name);
f1ac7d7859b26f0f36f5e8ffacda609f8ece80e5Stephen Gallagher if (s->comment_pathname)
f128b7b865062da662127712935dcc58bd022384Stephen Gallagher free(s->comment_pathname);
cc7ee57f3adada83ac657e69636ca995d5b6948eStephen Gallagher if (s->timestamp)
f128b7b865062da662127712935dcc58bd022384Stephen Gallagher free(s->timestamp);
5f216c753dbd2f2b25a011c5f705ee4f8ad924e6Simo Sorce if (s->lxcpath)
5f216c753dbd2f2b25a011c5f705ee4f8ad924e6Simo Sorce free(s->lxcpath);
3a4186ae40d0c3b7be46a4c973166f6048fcfe38Lukas Slebodnik}
5f216c753dbd2f2b25a011c5f705ee4f8ad924e6Simo Sorce
1171986bdc3011555c5b62a9d9ee9f7481f48cdcSimo Sorcestatic char *get_snapcomment_path(char* snappath, char *name)
10eae23e2483733d4ca3c21f15b5bdb3f04c9839Simo Sorce{
5f216c753dbd2f2b25a011c5f705ee4f8ad924e6Simo Sorce // $snappath/$name/comment
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt int ret, len = strlen(snappath) + strlen(name) + 10;
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt char *s = malloc(len);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (s) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = snprintf(s, len, "%s/%s/comment", snappath, name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0 || ret >= len) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(s);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer s = NULL;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer }
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer }
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer return s;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer}
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzerstatic char *get_timestamp(char* snappath, char *name)
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer{
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer char path[MAXPATHLEN], *s = NULL;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer int ret, len;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer FILE *fin;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer ret = snprintf(path, MAXPATHLEN, "%s/%s/ts", snappath, name);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer if (ret < 0 || ret >= MAXPATHLEN)
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer return NULL;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer if ((fin = fopen(path, "r")) == NULL)
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer return NULL;
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer (void) fseek(fin, 0, SEEK_END);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer len = ftell(fin);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer (void) fseek(fin, 0, SEEK_SET);
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer if (len > 0) {
b9c8ce2bdd4045782c243605a1b999098bedcffcNoam Meltzer s = malloc(len+1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (s) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher s[len] = '\0';
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (fread(s, 1, len, fin) != len) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("reading timestamp");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher free(s);
2b7349575770521243a34611e97d73790946a961Stephen Gallagher s = NULL;
683e1f67d08be7165ea456d4594c4c8a4eddc9b3Lukas Slebodnik }
683e1f67d08be7165ea456d4594c4c8a4eddc9b3Lukas Slebodnik }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt fclose(fin);
86b61156743b7ebdc049450a6f88452890fd9a61Jakub Hrozek return s;
d2d21d45a88d0869f860e215c2cf946f032818caLukas Slebodnik}
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher char snappath[MAXPATHLEN], path2[MAXPATHLEN];
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher int dirlen, count = 0, ret;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek struct dirent dirent, *direntp;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek struct lxc_snapshot *snaps =NULL, *nsnaps;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek DIR *dir;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek if (!c || !lxcapi_is_defined(c))
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek return -1;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek // snappath is ${lxcpath}snaps/${lxcname}/
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek dirlen = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name);
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek if (dirlen < 0 || dirlen >= MAXPATHLEN) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt ERROR("path name too long");
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt return -1;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek }
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek if (!(dir = opendir(snappath))) {
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina INFO("failed to open %s - assuming no snapshots", snappath);
42870c7ac3608ffc58f2c9524ad3dfc1401bc1aaPavel Březina return 0;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek }
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek while (!readdir_r(dir, &dirent, &direntp)) {
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek if (!direntp)
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek break;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (!strcmp(direntp->d_name, "."))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek continue;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (!strcmp(direntp->d_name, ".."))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek continue;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek ret = snprintf(path2, MAXPATHLEN, "%s/%s/config", snappath, direntp->d_name);
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt if (ret < 0 || ret >= MAXPATHLEN) {
654757bcead49427baaeb1b368c0e3433b67c51aJan Engelhardt ERROR("pathname too long");
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek goto out_free;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek }
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (!file_exists(path2))
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek continue;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek nsnaps = realloc(snaps, (count + 1)*sizeof(*snaps));
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (!nsnaps) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher SYSERROR("Out of memory");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out_free;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek snaps = nsnaps;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek snaps[count].free = lxcsnap_free;
70e59ed31c5a9c9ed02d9065ddf92be87c887efbJakub Hrozek snaps[count].name = strdup(direntp->d_name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!snaps[count].name)
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek goto out_free;
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek snaps[count].lxcpath = strdup(snappath);
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek if (!snaps[count].lxcpath) {
2cbdd12983eb85eddb90f64cfafb24eae5b448f4Jakub Hrozek free(snaps[count].name);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto out_free;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher snaps[count].comment_pathname = get_snapcomment_path(snappath, direntp->d_name);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher snaps[count].timestamp = get_timestamp(snappath, direntp->d_name);
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik count++;
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik }
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik if (closedir(dir))
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher WARN("failed to close directory");
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher *ret_snaps = snaps;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return count;
8ca73915a3bf60331468fed6b3b38652c979f95dJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherout_free:
619bd403265ce0880989ba6f8324b010949851bcSumit Bose if (snaps) {
796463906a54e259bd5b582ce84af4297a58eafcStephen Gallagher int i;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i=0; i<count; i++)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxcsnap_free(&snaps[i]);
ce35bb272d25926b8fa0f9450c8b74064f25c816Pavel Březina free(snaps);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return -1;
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny}
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny
755aee449c6311518200c2f11c1aae329a19b038Pavel Březinastatic bool lxcapi_snapshot_restore(struct lxc_container *c, char *snapname, char *newname)
97ae45d61d921f07e812620e0156aee02b7b83a7Stephen Gallagher{
f26c954658dfd7461f290f0b5d924951a6db219aJan Zeleny char clonelxcpath[MAXPATHLEN];
d42d371c00c83ae44b9d1c3e88ecbe0e01b112e6Stephen Gallagher int ret;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct lxc_container *snap, *rest;
619bd403265ce0880989ba6f8324b010949851bcSumit Bose struct bdev *bdev;
796463906a54e259bd5b582ce84af4297a58eafcStephen Gallagher bool b = false;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c || !c->name || !c->config_path)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return false;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher bdev = bdev_init(c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
ae8d047122c7ba8123f72b2eac68944868ac37d4Stephen Gallagher if (!bdev) {
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ERROR("Failed to find original backing store type");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return false;
7b5e7e539ae9312ab55d75aa94feaad549b2a708Pavel Březina }
25ac7bda643c8872b5a29bc856c374e76a7f8363Pavel Březina
82a4f022ec1cbb9530ffa21d95474152b24acf50Pavel Březina if (!newname)
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik newname = c->name;
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik if (strcmp(c->name, newname) == 0) {
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik if (!lxcapi_destroy(c)) {
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik ERROR("Could not destroy existing container %s", newname);
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik bdev_put(bdev);
7fc27c7a3ccbb6aecb8cf4a4a5f91962028cb897Lukas Slebodnik return false;
534c5427e5216d5d25f9b10925294e803ecf016fLukas Slebodnik }
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik }
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik ret = snprintf(clonelxcpath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name);
7fc27c7a3ccbb6aecb8cf4a4a5f91962028cb897Lukas Slebodnik if (ret < 0 || ret >= MAXPATHLEN) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher bdev_put(bdev);
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher return false;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher }
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher // how should we lock this?
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher snap = lxc_container_new(snapname, clonelxcpath);
0ca19d792b717456f334abdf35279acddf6d71c2Pavel Březina if (!snap || !lxcapi_is_defined(snap)) {
c407643004a02566e35a864ba0d8b0c0f88d9d67Pavel Březina ERROR("Could not open snapshot %s", snapname);
5f73b623fc72e3b9b3590420825f30e618b4d4ddPavel Březina if (snap) lxc_container_put(snap);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher bdev_put(bdev);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher return false;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher }
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher rest = lxcapi_clone(snap, newname, c->config_path, 0, bdev->type, NULL, 0, NULL);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher bdev_put(bdev);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher if (rest && lxcapi_is_defined(rest))
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher b = true;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher if (rest)
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik lxc_container_put(rest);
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley lxc_container_put(snap);
a2e417f38c57ed87c956ddcecf4dafca93842b65Lukas Slebodnik return b;
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley}
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elleystatic int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley{
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley va_list ap;
b1c4a998f8e217b4ba4cd632f5069d479211c22dYassir Elley const char **argv;
b1c4a998f8e217b4ba4cd632f5069d479211c22dYassir Elley int ret;
60cab26b12df9a2153823972cde0c38ca86e01b9Yassir Elley
b1c4a998f8e217b4ba4cd632f5069d479211c22dYassir Elley if (!c)
b1c4a998f8e217b4ba4cd632f5069d479211c22dYassir Elley return -1;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher va_start(ap, arg);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher argv = lxc_va_arg_list_to_argv_const(ap, 1);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher va_end(ap);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher if (!argv) {
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher ERROR("Memory allocation error.");
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher return -1;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher }
3441d0c2d11aea0c39b009751a1898333c009674Stephen Gallagher argv[0] = arg;
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik
45aeb924ec3ac448bb8d174a5cc061ed98b147c7Jakub Hrozek ret = lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek free((void*)argv);
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek return ret;
9df7cddb68c61ef4e0397c196604999c68f4be0dJakub Hrozek}
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnikstruct lxc_container *lxc_container_new(const char *name, const char *configpath)
717008c8c3f29f3a1a77266cc72a6cfa616bf295Benjamin Franzke{
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik struct lxc_container *c;
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik c = malloc(sizeof(*c));
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher if (!c) {
96453f402831275a39d5fb89c33c9776e148d03fStephen Gallagher fprintf(stderr, "failed to malloc lxc_container\n");
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher return NULL;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher }
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher memset(c, 0, sizeof(*c));
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (configpath)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->config_path = strdup(configpath);
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik else
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->config_path = strdup(default_lxc_path());
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik if (!c->config_path) {
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik fprintf(stderr, "Out of memory");
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher remove_trailing_slashes(c->config_path);
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher c->name = malloc(strlen(name)+1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!c->name) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fprintf(stderr, "Error allocating lxc_container name\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
04feeade1f6259368a6b23c6b3ecbad261161659Sumit Bose strcpy(c->name, name);
aec5785126354bd8b192f63fe04ea08dae9c0705Stephen Gallagher
769347ad4d35d43488eb98f980143495b0db415dStef Walter c->numthreads = 1;
769347ad4d35d43488eb98f980143495b0db415dStef Walter if (!(c->slock = lxc_newlock(c->config_path, name))) {
769347ad4d35d43488eb98f980143495b0db415dStef Walter fprintf(stderr, "failed to create lock\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!(c->privlock = lxc_newlock(NULL, NULL))) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher fprintf(stderr, "failed to alloc privlock\n");
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!set_config_filename(c)) {
225d845476b6136be9b77f528ed986bba7a7f732Simo Sorce fprintf(stderr, "Error allocating config file pathname\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (file_exists(c->configfile))
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher lxcapi_load_config(c, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ongoing_create(c) == 2) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ERROR("Error: %s creation was not completed", c->name);
6261893e00bd14fdd192ffc9a1379cb9c647d326Lukas Slebodnik lxcapi_destroy(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxc_conf_free(c->lxc_conf);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->lxc_conf = NULL;
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin }
22091abbe7b4a5667f62603dfd875e9ec6adf789Alexey Shabalin
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher // assign the member functions
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->is_defined = lxcapi_is_defined;
fe2091327ff44f80d6681c261494e4432404e9baStephen Gallagher c->state = lxcapi_state;
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik c->is_running = lxcapi_is_running;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher c->freeze = lxcapi_freeze;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->unfreeze = lxcapi_unfreeze;
e92ecf948387d1687a5e772ac86e606b1b6af957Stephen Gallagher c->console = lxcapi_console;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->console_getfd = lxcapi_console_getfd;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->init_pid = lxcapi_init_pid;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->load_config = lxcapi_load_config;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->want_daemonize = lxcapi_want_daemonize;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->start = lxcapi_start;
213ce2a78b1abe3921d8dc13c949a28130d00aecJan Zeleny c->startl = lxcapi_startl;
8b1f2574ce7a964965a18ab047ab09c4694380c4Jan Zeleny c->stop = lxcapi_stop;
e526b608657f229f7486b3aa8c53b0f2c53b42b1Jan Zeleny c->config_file_name = lxcapi_config_file_name;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->wait = lxcapi_wait;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->set_config_item = lxcapi_set_config_item;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher c->destroy = lxcapi_destroy;
ad07ed37b6b51ef134d4524edaf2259e19ac984fJan Zeleny c->save_config = lxcapi_save_config;
81165faf5d951aca69f410713730c26ff048ec44Sumit Bose c->get_keys = lxcapi_get_keys;
881c4ba834b23ae651ac01db667801f314eb0a5dJan Zeleny c->create = lxcapi_create;
caee9828ee30609e9f433957dbb3d0163390a207Sumit Bose c->createl = lxcapi_createl;
0f3df54840ec9a050cc0b1b68269c3f28c859e64Sumit Bose c->shutdown = lxcapi_shutdown;
8eb981dd8bc85aee7a913c6f0096ad47f3382339Sumit Bose c->reboot = lxcapi_reboot;
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose c->clear_config_item = lxcapi_clear_config_item;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->get_config_item = lxcapi_get_config_item;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->get_cgroup_item = lxcapi_get_cgroup_item;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->set_cgroup_item = lxcapi_set_cgroup_item;
71ad247500b417836a1a2edec257a4433a7c415fJan Zeleny c->get_config_path = lxcapi_get_config_path;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->set_config_path = lxcapi_set_config_path;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->clone = lxcapi_clone;
e134a6af42102c8d865e82bf89e0b8c5a40fb5faStephen Gallagher c->get_ips = lxcapi_get_ips;
38e2ec1c757955ab557fd95807afa58042d09482Jan Zeleny c->attach = lxcapi_attach;
1a853121ca2ba8ede6df429ee76942131ffb0f65Jan Zeleny c->attach_run_wait = lxcapi_attach_run_wait;
88275cccddf39892e01682b39b02292eb74729bdPavel Březina c->attach_run_waitl = lxcapi_attach_run_waitl;
8ff0aba893d8da1a8163ccaf9ad2c5b6bccd121fSumit Bose c->snapshot = lxcapi_snapshot;
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek c->snapshot_list = lxcapi_snapshot_list;
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek c->snapshot_restore = lxcapi_snapshot_restore;
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek /* we'll allow the caller to update these later */
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
cc1c033c34b5f816b633d27a21aefbf811a7cf72Lukas Slebodnik fprintf(stderr, "failed to open log\n");
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher goto err;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
41402c003fef1e6768f5468dd7ea2e20e16bfa19Benjamin Franzke
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return c;
3275c56e7b5dd36d25e0a971bf90c70179f0ab8fLukas Slebodnik
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallaghererr:
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher lxc_container_free(c);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
f8a4a5f6240156809e1b5ef03816f673281e3fa0Jakub Hrozek
88aeed9a31b734a92630d5e881c960c5f77ba0ceJakub Hrozekint lxc_get_wait_states(const char **states)
5bcb59c94ceb86b4ccd280a5a3f47c16fb08aac3Lukas Slebodnik{
12805da52a93c268290cec7b8fbbdbd4ea8abc3eLukas Slebodnik int i;
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher
92ae9d2b909d0fd4a522a270157926878b5d0862Stephen Gallagher if (states)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher for (i=0; i<MAX_STATE; i++)
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek states[i] = lxc_state2str(i);
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek return MAX_STATE;
42ec8af02ecf1937e4db9b1ecc6216022634f0f9Michal Zidek}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher