~kampka/ubuntu/quantal/lxc/upstart-instance

« back to all changes in this revision

Viewing changes to .pc/0202-make-api-start-reliable/src/lxc/lxccontainer.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber, Serge Hallyn, Stéphane Graber
  • Date: 2012-08-25 12:44:17 UTC
  • Revision ID: package-import@ubuntu.com-20120825124417-yn1xu1x10fi7o972
Tags: 0.8.0~rc1-4ubuntu29
[ Serge Hallyn ]
* fix lxcapi_start to not return true when it container failed to start.
* 0201-fix-mkdir-race: don't raise error if mkdir fails with EEXIST.
* 0202-make-api-start-reliable: have daemonized start through the api
  wait until the container is RUNNING before returning true.  If a 5
  second timeout is hit before the container is RUNNING, return false.

[ Stéphane Graber ]
* python-lxc: in get_ips() if timeout is 1 don't wait one second before
  returning.
* python-lxc: Add import time warning that the API isn't yet stable and
  so may change at any point in the future.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* liblxcapi
 
2
 *
 
3
 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
 
4
 * Copyright © 2012 Canonical Ltd.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License version 2, as
 
8
 * published by the Free Software Foundation.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
#include "lxc.h"
 
21
#include "state.h"
 
22
#include "lxccontainer.h"
 
23
#include "conf.h"
 
24
#include "config.h"
 
25
#include "confile.h"
 
26
#include "cgroup.h"
 
27
#include "commands.h"
 
28
#include "log.h"
 
29
#include <unistd.h>
 
30
#include <sys/types.h>
 
31
#include <sys/wait.h>
 
32
#include <errno.h>
 
33
 
 
34
lxc_log_define(lxc_container, lxc);
 
35
 
 
36
/* LOCKING
 
37
 * c->privlock protects the struct lxc_container from multiple threads.
 
38
 * c->slock protects the on-disk container data
 
39
 * NOTHING mutexes two independent programs with their own struct
 
40
 * lxc_container for the same c->name, between API calls.  For instance,
 
41
 * c->config_read(); c->start();  Between those calls, data on disk
 
42
 * could change (which shouldn't bother the caller unless for instance
 
43
 * the rootfs get moved).  c->config_read(); update; c->config_write();
 
44
 * Two such updaters could race.  The callers should therefore check their
 
45
 * results.  Trying to prevent that would necessarily expose us to deadlocks
 
46
 * due to hung callers.  So I prefer to keep the locks only within our own
 
47
 * functions, not across functions.
 
48
 *
 
49
 * If you're going to fork while holding a lxccontainer, increment
 
50
 * c->numthreads (under privlock) before forking.  When deleting,
 
51
 * decrement numthreads under privlock, then if it hits 0 you can delete.
 
52
 * Do not ever use a lxccontainer whose numthreads you did not bump.
 
53
 */
 
54
 
 
55
static void lxc_container_free(struct lxc_container *c)
 
56
{
 
57
        if (!c)
 
58
                return;
 
59
 
 
60
        if (c->configfile) {
 
61
                free(c->configfile);
 
62
                c->configfile = NULL;
 
63
        }
 
64
        if (c->error_string) {
 
65
                free(c->error_string);
 
66
                c->error_string = NULL;
 
67
        }
 
68
        if (c->privlock) {
 
69
                sem_destroy(c->privlock);
 
70
                free(c->privlock);
 
71
                c->privlock = NULL;
 
72
        }
 
73
        if (c->name) {
 
74
                free(c->name);
 
75
                c->name = NULL;
 
76
        }
 
77
        /*
 
78
         * XXX TODO
 
79
         * note, c->lxc_conf is going to have to be freed, but the fn
 
80
         * to do that hasn't been written yet near as I can tell
 
81
         */
 
82
        free(c);
 
83
}
 
84
 
 
85
int lxc_container_get(struct lxc_container *c)
 
86
{
 
87
        if (!c)
 
88
                return 0;
 
89
 
 
90
        if (lxclock(c->privlock, 0))
 
91
                return 0;
 
92
        if (c->numthreads < 1) {
 
93
                // bail without trying to unlock, bc the privlock is now probably
 
94
                // in freed memory
 
95
                return 0;
 
96
        }
 
97
        c->numthreads++;
 
98
        lxcunlock(c->privlock);
 
99
        return 1;
 
100
}
 
101
 
 
102
int lxc_container_put(struct lxc_container *c)
 
103
{
 
104
        if (!c)
 
105
                return -1;
 
106
        if (lxclock(c->privlock, 0))
 
107
                return -1;
 
108
        if (--c->numthreads < 1) {
 
109
                lxcunlock(c->privlock);
 
110
                lxc_container_free(c);
 
111
                return 1;
 
112
        }
 
113
        lxcunlock(c->privlock);
 
114
        return 0;
 
115
}
 
116
 
 
117
static bool file_exists(char *f)
 
118
{
 
119
        struct stat statbuf;
 
120
 
 
121
        return stat(f, &statbuf) == 0;
 
122
}
 
123
 
 
124
static bool lxcapi_is_defined(struct lxc_container *c)
 
125
{
 
126
        struct stat statbuf;
 
127
        bool ret = false;
 
128
        int statret;
 
129
 
 
130
        if (!c)
 
131
                return false;
 
132
 
 
133
        if (lxclock(c->privlock, 0))
 
134
                return false;
 
135
        if (!c->configfile)
 
136
                goto out;
 
137
        statret = stat(c->configfile, &statbuf);
 
138
        if (statret != 0)
 
139
                goto out;
 
140
        ret = true;
 
141
 
 
142
out:
 
143
        lxcunlock(c->privlock);
 
144
        return ret;
 
145
}
 
146
 
 
147
static const char *lxcapi_state(struct lxc_container *c)
 
148
{
 
149
        const char *ret;
 
150
        lxc_state_t s;
 
151
 
 
152
        if (!c)
 
153
                return NULL;
 
154
        if (lxclock(c->slock, 0))
 
155
                return NULL;
 
156
        s = lxc_getstate(c->name);
 
157
        ret = lxc_state2str(s);
 
158
        lxcunlock(c->slock);
 
159
 
 
160
        return ret;
 
161
}
 
162
 
 
163
static bool lxcapi_is_running(struct lxc_container *c)
 
164
{
 
165
        const char *s;
 
166
 
 
167
        if (!c)
 
168
                return false;
 
169
        s = lxcapi_state(c);
 
170
        if (!s || strcmp(s, "STOPPED") == 0)
 
171
                return false;
 
172
        return true;
 
173
}
 
174
 
 
175
static bool lxcapi_freeze(struct lxc_container *c)
 
176
{
 
177
        int ret;
 
178
        if (!c)
 
179
                return false;
 
180
 
 
181
        if (lxclock(c->slock, 0))
 
182
                return false;
 
183
        ret = lxc_freeze(c->name);
 
184
        lxcunlock(c->slock);
 
185
        if (ret)
 
186
                return false;
 
187
        return true;
 
188
}
 
189
 
 
190
static bool lxcapi_unfreeze(struct lxc_container *c)
 
191
{
 
192
        int ret;
 
193
        if (!c)
 
194
                return false;
 
195
 
 
196
        if (lxclock(c->slock, 0))
 
197
                return false;
 
198
        ret = lxc_unfreeze(c->name);
 
199
        lxcunlock(c->slock);
 
200
        if (ret)
 
201
                return false;
 
202
        return true;
 
203
}
 
204
 
 
205
static pid_t lxcapi_init_pid(struct lxc_container *c)
 
206
{
 
207
        pid_t ret;
 
208
        if (!c)
 
209
                return -1;
 
210
 
 
211
        if (lxclock(c->slock, 0))
 
212
                return -1;
 
213
        ret = get_init_pid(c->name);
 
214
        lxcunlock(c->slock);
 
215
        return ret;
 
216
}
 
217
 
 
218
static bool lxcapi_load_config(struct lxc_container *c, char *alt_file)
 
219
{
 
220
        bool ret = false;
 
221
        char *fname;
 
222
        if (!c)
 
223
                return false;
 
224
 
 
225
        fname = c->configfile;
 
226
        if (alt_file)
 
227
                fname = alt_file;
 
228
        if (!fname)
 
229
                return false;
 
230
        if (lxclock(c->slock, 0))
 
231
                return false;
 
232
        if (!c->lxc_conf)
 
233
                c->lxc_conf = lxc_conf_init();
 
234
        if (c->lxc_conf && !lxc_config_read(fname, c->lxc_conf))
 
235
                ret = true;
 
236
        lxcunlock(c->slock);
 
237
        return ret;
 
238
}
 
239
 
 
240
static void lxcapi_want_daemonize(struct lxc_container *c)
 
241
{
 
242
        if (!c)
 
243
                return;
 
244
        c->daemonize = 1;
 
245
}
 
246
 
 
247
/*
 
248
 * I can't decide if it'd be more convenient for callers if we accept '...',
 
249
 * or a null-terminated array (i.e. execl vs execv)
 
250
 */
 
251
static bool lxcapi_start(struct lxc_container *c, int useinit, char ** argv)
 
252
{
 
253
        int ret;
 
254
        struct lxc_conf *conf;
 
255
        int daemonize = 0;
 
256
        char *default_args[] = {
 
257
                "/sbin/init",
 
258
                '\0',
 
259
        };
 
260
 
 
261
        /* container exists */
 
262
        if (!c)
 
263
                return false;
 
264
        /* container has been setup */
 
265
        if (!c->lxc_conf)
 
266
                return false;
 
267
 
 
268
        /* is this app meant to be run through lxcinit, as in lxc-execute? */
 
269
        if (useinit && !argv)
 
270
                return false;
 
271
 
 
272
        if (lxclock(c->privlock, 0))
 
273
                return false;
 
274
        conf = c->lxc_conf;
 
275
        daemonize = c->daemonize;
 
276
        lxcunlock(c->privlock);
 
277
 
 
278
        if (useinit) {
 
279
                ret = lxc_execute(c->name, argv, 1, conf);
 
280
                return ret == 0 ? true : false;
 
281
        }
 
282
 
 
283
        if (!argv)
 
284
                argv = default_args;
 
285
 
 
286
        /*
 
287
        * say, I'm not sure - what locks do we want here?  Any?
 
288
        * Is liblxc's locking enough here to protect the on disk
 
289
        * container?  We don't want to exclude things like lxc_info
 
290
        * while container is running...
 
291
        */
 
292
        if (daemonize) {
 
293
                if (!lxc_container_get(c))
 
294
                        return false;
 
295
                pid_t pid = fork();
 
296
                if (pid < 0) {
 
297
                        lxc_container_put(c);
 
298
                        return false;
 
299
                }
 
300
                if (pid != 0)
 
301
                        return true;
 
302
                /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */
 
303
                chdir("/");
 
304
                close(0);
 
305
                close(1);
 
306
                close(2);
 
307
                open("/dev/null", O_RDONLY);
 
308
                open("/dev/null", O_RDWR);
 
309
                open("/dev/null", O_RDWR);
 
310
                setsid();
 
311
        }
 
312
 
 
313
        if (putenv("container=lxc")) {
 
314
                fprintf(stderr, "failed to set environment variable");
 
315
                if (daemonize) {
 
316
                        lxc_container_put(c);
 
317
                        exit(1);
 
318
                } else {
 
319
                        return false;
 
320
                }
 
321
        }
 
322
 
 
323
reboot:
 
324
        conf->reboot = 0;
 
325
        ret = lxc_start(c->name, argv, conf);
 
326
 
 
327
        if (conf->reboot) {
 
328
                INFO("container requested reboot");
 
329
                conf->reboot = 0;
 
330
                if (conf->maincmd_fd)
 
331
                        close(conf->maincmd_fd);
 
332
                conf->maincmd_fd = 0;
 
333
                goto reboot;
 
334
        }
 
335
 
 
336
        if (daemonize) {
 
337
                lxc_container_put(c);
 
338
                exit (ret == 0 ? true : false);
 
339
        } else {
 
340
                return (ret == 0 ? true : false);
 
341
        }
 
342
}
 
343
 
 
344
/*
 
345
 * note there MUST be an ending NULL
 
346
 */
 
347
static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
 
348
{
 
349
        va_list ap;
 
350
        char **inargs = NULL, **temp;
 
351
        int n_inargs = 0;
 
352
        bool bret = false;
 
353
 
 
354
        /* container exists */
 
355
        if (!c)
 
356
                return false;
 
357
 
 
358
        /* build array of arguments if any */
 
359
        va_start(ap, useinit);
 
360
        while (1) {
 
361
                char *arg;
 
362
                arg = va_arg(ap, char *);
 
363
                if (!arg)
 
364
                        break;
 
365
                n_inargs++;
 
366
                temp = realloc(inargs, n_inargs * sizeof(*inargs));
 
367
                if (!temp)
 
368
                        goto out;
 
369
                inargs = temp;
 
370
                inargs[n_inargs - 1] = strdup(arg);  // not sure if it's safe not to copy
 
371
        }
 
372
        va_end(ap);
 
373
 
 
374
        /* add trailing NULL */
 
375
        if (n_inargs) {
 
376
                n_inargs++;
 
377
                temp = realloc(inargs, n_inargs * sizeof(*inargs));
 
378
                if (!temp)
 
379
                        goto out;
 
380
                inargs = temp;
 
381
                inargs[n_inargs - 1] = NULL;
 
382
        }
 
383
 
 
384
        bret = lxcapi_start(c, useinit, inargs);
 
385
 
 
386
out:
 
387
        if (inargs) {
 
388
                int i;
 
389
                for (i = 0; i < n_inargs; i++) {
 
390
                        if (inargs[i])
 
391
                                free(inargs[i]);
 
392
                }
 
393
                free(inargs);
 
394
        }
 
395
 
 
396
        return bret;
 
397
}
 
398
 
 
399
static bool lxcapi_stop(struct lxc_container *c)
 
400
{
 
401
        int ret;
 
402
 
 
403
        if (!c)
 
404
                return false;
 
405
 
 
406
        ret = lxc_stop(c->name);
 
407
 
 
408
        return ret == 0;
 
409
}
 
410
 
 
411
static bool lxcapi_wait(struct lxc_container *c, char *state, int timeout)
 
412
{
 
413
        int ret;
 
414
 
 
415
        if (!c)
 
416
                return false;
 
417
 
 
418
        ret = lxc_wait(c->name, state, timeout);
 
419
        return ret == 0;
 
420
}
 
421
 
 
422
static bool valid_template(char *t)
 
423
{
 
424
        struct stat statbuf;
 
425
        int statret;
 
426
 
 
427
        statret = stat(t, &statbuf);
 
428
        if (statret == 0)
 
429
                return true;
 
430
        return false;
 
431
}
 
432
 
 
433
/*
 
434
 * create the standard expected container dir
 
435
 */
 
436
static bool create_container_dir(struct lxc_container *c)
 
437
{
 
438
        char *s;
 
439
        int len, ret;
 
440
 
 
441
        len = strlen(LXCPATH) + strlen(c->name) + 2;
 
442
        s = malloc(len);
 
443
        if (!s)
 
444
                return false;
 
445
        ret = snprintf(s, len, "%s/%s", LXCPATH, c->name);
 
446
        if (ret < 0 || ret >= len) {
 
447
                free(s);
 
448
                return false;
 
449
        }
 
450
        ret = mkdir(s, 0755);
 
451
        if (ret) {
 
452
                if (errno == EEXIST)
 
453
                        ret = 0;
 
454
                else
 
455
                        SYSERROR("failed to create container path for %s\n", c->name);
 
456
        }
 
457
        free(s);
 
458
        return ret == 0;
 
459
}
 
460
 
 
461
/*
 
462
 * backing stores not (yet) supported
 
463
 * for ->create, argv contains the arguments to pass to the template,
 
464
 * terminated by NULL.  If no arguments, you can just pass NULL.
 
465
 */
 
466
static bool lxcapi_create(struct lxc_container *c, char *t, char **argv)
 
467
{
 
468
        bool bret = false;
 
469
        pid_t pid;
 
470
        int ret, status;
 
471
        char *tpath = NULL;
 
472
        int len, nargs = 0;
 
473
        char **newargv;
 
474
 
 
475
        if (!c)
 
476
                return false;
 
477
 
 
478
        len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
 
479
        tpath = malloc(len);
 
480
        if (!tpath)
 
481
                return false;
 
482
        ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
 
483
        if (ret < 0 || ret >= len)
 
484
                goto out;
 
485
        if (!valid_template(tpath)) {
 
486
                ERROR("bad template: %s\n", t);
 
487
                goto out;
 
488
        }
 
489
 
 
490
        if (!create_container_dir(c))
 
491
                goto out;
 
492
 
 
493
        if (!c->save_config(c, NULL)) {
 
494
                ERROR("failed to save starting configuration for %s\n", c->name);
 
495
                goto out;
 
496
        }
 
497
 
 
498
        /* we're going to fork.  but since we'll wait for our child, we
 
499
           don't need to lxc_container_get */
 
500
 
 
501
        if (lxclock(c->slock, 0)) {
 
502
                ERROR("failed to grab global container lock for %s\n", c->name);
 
503
                goto out;
 
504
        }
 
505
 
 
506
        pid = fork();
 
507
        if (pid < 0) {
 
508
                SYSERROR("failed to fork task for container creation template\n");
 
509
                goto out_unlock;
 
510
        }
 
511
 
 
512
        if (pid == 0) { // child
 
513
                char *patharg, *namearg;
 
514
                int i;
 
515
 
 
516
                close(0);
 
517
                close(1);
 
518
                close(2);
 
519
                open("/dev/null", O_RDONLY);
 
520
                open("/dev/null", O_RDWR);
 
521
                open("/dev/null", O_RDWR);
 
522
 
 
523
                /*
 
524
                 * create our new array, pre-pend the template name and
 
525
                 * base args
 
526
                 */
 
527
                if (argv)
 
528
                        for (; argv[nargs]; nargs++) ;
 
529
                nargs += 3;  // template, path and name args
 
530
                newargv = malloc(nargs * sizeof(*newargv));
 
531
                if (!newargv)
 
532
                        exit(1);
 
533
                newargv[0] = t;
 
534
 
 
535
                len = strlen(LXCPATH) + strlen(c->name) + strlen("--path=") + 2;
 
536
                patharg = malloc(len);
 
537
                if (!patharg)
 
538
                        exit(1);
 
539
                ret = snprintf(patharg, len, "--path=%s/%s", LXCPATH, c->name);
 
540
                if (ret < 0 || ret >= len)
 
541
                        exit(1);
 
542
                newargv[1] = patharg;
 
543
                len = strlen("--name=") + strlen(c->name) + 1;
 
544
                namearg = malloc(len);
 
545
                if (!namearg)
 
546
                        exit(1);
 
547
                ret = snprintf(namearg, len, "--name=%s", c->name);
 
548
                if (ret < 0 || ret >= len)
 
549
                        exit(1);
 
550
                newargv[2] = namearg;
 
551
 
 
552
                /* add passed-in args */
 
553
                if (argv)
 
554
                        for (i = 3; i < nargs; i++)
 
555
                                newargv[i] = argv[i-3];
 
556
 
 
557
                /* add trailing NULL */
 
558
                nargs++;
 
559
                newargv = realloc(newargv, nargs * sizeof(*newargv));
 
560
                if (!newargv)
 
561
                        exit(1);
 
562
                newargv[nargs - 1] = NULL;
 
563
 
 
564
                /* execute */
 
565
                ret = execv(tpath, newargv);
 
566
                SYSERROR("failed to execute template %s", tpath);
 
567
                exit(1);
 
568
        }
 
569
 
 
570
again:
 
571
        ret = waitpid(pid, &status, 0);
 
572
        if (ret == -1) {
 
573
                if (errno == -EINTR)
 
574
                        goto again;
 
575
                SYSERROR("waitpid failed");
 
576
                goto out_unlock;
 
577
        }
 
578
        if (ret != pid)
 
579
                goto again;
 
580
        if (!WIFEXITED(status))  { // did not exit normally
 
581
                // we could set an error code and string inside the
 
582
                // container_struct here if we like
 
583
                ERROR("container creation template exited abnormally\n");
 
584
                goto out_unlock;
 
585
        }
 
586
 
 
587
        if (WEXITSTATUS(status) != 0)
 
588
                ERROR("container creation template for %s exited with %d\n",
 
589
                      c->name, WEXITSTATUS(status));
 
590
        else
 
591
                bret = true;
 
592
 
 
593
out_unlock:
 
594
        lxcunlock(c->slock);
 
595
out:
 
596
        if (tpath)
 
597
                free(tpath);
 
598
        return bret;
 
599
}
 
600
 
 
601
static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
 
602
{
 
603
        bool retv;
 
604
        pid_t pid;
 
605
 
 
606
        if (!c)
 
607
                return false;
 
608
 
 
609
        if (!timeout)
 
610
                timeout = -1;
 
611
        if (!c->is_running(c))
 
612
                return true;
 
613
        pid = c->init_pid(c);
 
614
        if (pid <= 0)
 
615
                return true;
 
616
        kill(pid, SIGPWR);
 
617
        retv = c->wait(c, "STOPPED", timeout);
 
618
        if (timeout > 0) {
 
619
                c->stop(c);
 
620
                retv = c->wait(c, "STOPPED", 0); // 0 means don't wait
 
621
        }
 
622
        return retv;
 
623
}
 
624
 
 
625
static bool lxcapi_createl(struct lxc_container *c, char *t, ...)
 
626
{
 
627
        bool bret = false;
 
628
        char **args = NULL, **temp;
 
629
        va_list ap;
 
630
        int nargs = 0;
 
631
 
 
632
        if (!c)
 
633
                return false;
 
634
 
 
635
        /*
 
636
         * since we're going to wait for create to finish, I don't think we
 
637
         * need to get a copy of the arguments.
 
638
         */
 
639
        va_start(ap, t);
 
640
        while (1) {
 
641
                char *arg;
 
642
                arg = va_arg(ap, char *);
 
643
                if (!arg)
 
644
                        break;
 
645
                nargs++;
 
646
                temp = realloc(args, nargs * sizeof(*args));
 
647
                if (!temp)
 
648
                        goto out;
 
649
                args = temp;
 
650
                args[nargs - 1] = arg;
 
651
        }
 
652
        va_end(ap);
 
653
 
 
654
        bret = c->create(c, t, args);
 
655
 
 
656
out:
 
657
        if (args)
 
658
                free(args);
 
659
        return bret;
 
660
}
 
661
 
 
662
static bool lxcapi_clear_config_item(struct lxc_container *c, char *key)
 
663
{
 
664
        int ret;
 
665
 
 
666
        if (!c || !c->lxc_conf)
 
667
                return false;
 
668
        if (lxclock(c->privlock, 0)) {
 
669
                return false;
 
670
        }
 
671
        ret = lxc_clear_config_item(c->lxc_conf, key);
 
672
        lxcunlock(c->privlock);
 
673
        return ret == 0;
 
674
}
 
675
 
 
676
static int lxcapi_get_config_item(struct lxc_container *c, char *key, char *retv, int inlen)
 
677
{
 
678
        int ret;
 
679
 
 
680
        if (!c || !c->lxc_conf)
 
681
                return -1;
 
682
        if (lxclock(c->privlock, 0)) {
 
683
                return -1;
 
684
        }
 
685
        ret = lxc_get_config_item(c->lxc_conf, key, retv, inlen);
 
686
        lxcunlock(c->privlock);
 
687
        return ret;
 
688
}
 
689
 
 
690
static int lxcapi_get_keys(struct lxc_container *c, char *key, char *retv, int inlen)
 
691
{
 
692
        if (!key)
 
693
                return lxc_listconfigs(retv, inlen);
 
694
        /*
 
695
         * Support 'lxc.network.<idx>', i.e. 'lxc.network.0'
 
696
         * This is an intelligent result to show which keys are valid given
 
697
         * the type of nic it is
 
698
         */
 
699
        if (!c || !c->lxc_conf)
 
700
                return -1;
 
701
        if (lxclock(c->privlock, 0))
 
702
                return -1;
 
703
        int ret = -1;
 
704
        if (strncmp(key, "lxc.network.", 12) == 0)
 
705
                ret =  lxc_list_nicconfigs(c->lxc_conf, key, retv, inlen);
 
706
        lxcunlock(c->privlock);
 
707
        return ret;
 
708
}
 
709
 
 
710
 
 
711
/* default config file - should probably come through autoconf */
 
712
#define LXC_DEFAULT_CONFIG "/etc/lxc/lxc.conf"
 
713
static bool lxcapi_save_config(struct lxc_container *c, char *alt_file)
 
714
{
 
715
        if (!alt_file)
 
716
                alt_file = c->configfile;
 
717
        if (!alt_file)
 
718
                return false;  // should we write to stdout if no file is specified?
 
719
        if (!c->lxc_conf)
 
720
                if (!c->load_config(c, LXC_DEFAULT_CONFIG)) {
 
721
                        ERROR("Error loading default configuration file %s while saving %s\n", LXC_DEFAULT_CONFIG, c->name);
 
722
                        return false;
 
723
                }
 
724
 
 
725
        FILE *fout = fopen(alt_file, "w");
 
726
        if (!fout)
 
727
                return false;
 
728
        if (lxclock(c->privlock, 0)) {
 
729
                fclose(fout);
 
730
                return false;
 
731
        }
 
732
        write_config(fout, c->lxc_conf);
 
733
        fclose(fout);
 
734
        lxcunlock(c->privlock);
 
735
        return true;
 
736
}
 
737
 
 
738
static bool lxcapi_destroy(struct lxc_container *c)
 
739
{
 
740
        pid_t pid;
 
741
        int ret, status;
 
742
 
 
743
        if (!c)
 
744
                return false;
 
745
 
 
746
        pid = fork();
 
747
        if (pid < 0)
 
748
                return false;
 
749
        if (pid == 0) { // child
 
750
                ret = execlp("lxc-destroy", "lxc-destroy", "-n", c->name, NULL);
 
751
                perror("execl");
 
752
                exit(1);
 
753
        }
 
754
 
 
755
again:
 
756
        ret = waitpid(pid, &status, 0);
 
757
        if (ret == -1) {
 
758
                if (errno == -EINTR)
 
759
                        goto again;
 
760
                perror("waitpid");
 
761
                return false;
 
762
        }
 
763
        if (ret != pid)
 
764
                goto again;
 
765
        if (!WIFEXITED(status))  { // did not exit normally
 
766
                // we could set an error code and string inside the
 
767
                // container_struct here if we like
 
768
                return false;
 
769
        }
 
770
 
 
771
        return WEXITSTATUS(status) == 0;
 
772
}
 
773
 
 
774
static bool lxcapi_set_config_item(struct lxc_container *c, char *key, char *v)
 
775
{
 
776
        int ret;
 
777
        bool b = false;
 
778
        struct lxc_config_t *config;
 
779
 
 
780
        if (!c)
 
781
                return false;
 
782
 
 
783
        if (lxclock(c->privlock, 0))
 
784
                return false;
 
785
 
 
786
        if (!c->lxc_conf)
 
787
                c->lxc_conf = lxc_conf_init();
 
788
        if (!c->lxc_conf)
 
789
                goto err;
 
790
        config = lxc_getconfig(key);
 
791
        if (!config)
 
792
                goto err;
 
793
        ret = config->cb(key, v, c->lxc_conf);
 
794
        if (!ret)
 
795
                b = true;
 
796
 
 
797
err:
 
798
        lxcunlock(c->privlock);
 
799
        return b;
 
800
}
 
801
 
 
802
static char *lxcapi_config_file_name(struct lxc_container *c)
 
803
{
 
804
        if (!c || !c->configfile)
 
805
                return NULL;
 
806
        return strdup(c->configfile);
 
807
}
 
808
 
 
809
struct lxc_container *lxc_container_new(char *name)
 
810
{
 
811
        struct lxc_container *c;
 
812
        int ret, len;
 
813
 
 
814
        c = malloc(sizeof(*c));
 
815
        if (!c) {
 
816
                fprintf(stderr, "failed to malloc lxc_container\n");
 
817
                return NULL;
 
818
        }
 
819
        memset(c, 0, sizeof(*c));
 
820
 
 
821
        c->name = malloc(strlen(name)+1);
 
822
        if (!c->name) {
 
823
                fprintf(stderr, "Error allocating lxc_container name\n");
 
824
                goto err;
 
825
        }
 
826
        strcpy(c->name, name);
 
827
 
 
828
        c->numthreads = 1;
 
829
        c->slock = lxc_newlock(name);
 
830
        if (!c->slock) {
 
831
                fprintf(stderr, "failed to create lock\n");
 
832
                goto err;
 
833
        }
 
834
 
 
835
        c->privlock = lxc_newlock(NULL);
 
836
        if (!c->privlock) {
 
837
                fprintf(stderr, "failed to alloc privlock\n");
 
838
                goto err;
 
839
        }
 
840
 
 
841
        len = strlen(LXCDIR)+strlen(c->name)+strlen("/config")+2;
 
842
        c->configfile = malloc(len);
 
843
        if (!c->configfile) {
 
844
                fprintf(stderr, "Error allocating config file pathname\n");
 
845
                goto err;
 
846
        }
 
847
        ret = snprintf(c->configfile, len, "%s/%s/config", LXCDIR, c->name);
 
848
        if (ret < 0 || ret >= len) {
 
849
                fprintf(stderr, "Error printing out config file name\n");
 
850
                goto err;
 
851
        }
 
852
 
 
853
        if (file_exists(c->configfile))
 
854
                lxcapi_load_config(c, NULL);
 
855
 
 
856
        // assign the member functions
 
857
        c->is_defined = lxcapi_is_defined;
 
858
        c->state = lxcapi_state;
 
859
        c->is_running = lxcapi_is_running;
 
860
        c->freeze = lxcapi_freeze;
 
861
        c->unfreeze = lxcapi_unfreeze;
 
862
        c->init_pid = lxcapi_init_pid;
 
863
        c->load_config = lxcapi_load_config;
 
864
        c->want_daemonize = lxcapi_want_daemonize;
 
865
        c->start = lxcapi_start;
 
866
        c->startl = lxcapi_startl;
 
867
        c->stop = lxcapi_stop;
 
868
        c->config_file_name = lxcapi_config_file_name;
 
869
        c->wait = lxcapi_wait;
 
870
        c->set_config_item = lxcapi_set_config_item;
 
871
        c->destroy = lxcapi_destroy;
 
872
        c->save_config = lxcapi_save_config;
 
873
        c->get_keys = lxcapi_get_keys;
 
874
        c->create = lxcapi_create;
 
875
        c->createl = lxcapi_createl;
 
876
        c->shutdown = lxcapi_shutdown;
 
877
        c->clear_config_item = lxcapi_clear_config_item;
 
878
        c->get_config_item = lxcapi_get_config_item;
 
879
 
 
880
        /* we'll allow the caller to update these later */
 
881
        if (lxc_log_init("/var/log/lxccontainer.log", "trace", "lxc_container", 0)) {
 
882
                fprintf(stderr, "failed to open log\n");
 
883
                goto err;
 
884
        }
 
885
 
 
886
        /*
 
887
         * default configuration file is $LXCDIR/$NAME/config
 
888
         */
 
889
 
 
890
        return c;
 
891
 
 
892
err:
 
893
        lxc_container_free(c);
 
894
        return NULL;
 
895
}
 
896
 
 
897
int lxc_get_wait_states(char **states)
 
898
{
 
899
        int i;
 
900
 
 
901
        if (states)
 
902
                for (i=0; i<MAX_STATE; i++)
 
903
                        states[i] = lxc_state2str(i);
 
904
        return MAX_STATE;
 
905
}