]> git.proxmox.com Git - mirror_lxc.git/blame - src/lua-lxc/core.c
tree-wide: cleanup
[mirror_lxc.git] / src / lua-lxc / core.c
CommitLineData
f080ffd7
DE
1/*
2 * lua-lxc: lua bindings for lxc
3 *
4 * Copyright © 2012 Oracle.
5 *
6 * Authors:
7 * Dwight Engen <dwight.engen@oracle.com>
8 *
c66e9b01
SH
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
f080ffd7
DE
22 */
23
24#define LUA_LIB
25#define _GNU_SOURCE
26#include <lua.h>
27#include <lauxlib.h>
44a80d67 28#include <assert.h>
f080ffd7 29#include <string.h>
ac825528 30#include <unistd.h>
c25c2970 31#include <libgen.h>
f080ffd7 32#include <lxc/lxccontainer.h>
f2363e38 33#include "lxc/commands.h"
f080ffd7 34
44a80d67
NC
35#if LUA_VERSION_NUM < 502
36#define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l))
37#define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l))
ac825528 38#define luaL_checkunsigned(L,n) luaL_checknumber(L,n)
44a80d67
NC
39#endif
40
67f69573 41#if LUA_VERSION_NUM >= 503
98088cfb 42#ifndef luaL_checkunsigned
67f69573
TM
43#define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n))
44#endif
98088cfb 45#endif
67f69573 46
f080ffd7
DE
47#ifdef NO_CHECK_UDATA
48#define checkudata(L,i,tname) lua_touserdata(L, i)
49#else
50#define checkudata(L,i,tname) luaL_checkudata(L, i, tname)
51#endif
52
53#define lua_boxpointer(L,u) \
54 (*(void **) (lua_newuserdata(L, sizeof(void *))) = (u))
55
56#define lua_unboxpointer(L,i,tname) \
57 (*(void **) (checkudata(L, i, tname)))
58
59#define CONTAINER_TYPENAME "lxc.container"
60
9bfdc223
AJM
61/* Max Lua arguments for function */
62#define MAXVARS 200
63
f080ffd7
DE
64static int container_new(lua_State *L)
65{
83c98d82 66 struct lxc_container *c;
f080ffd7 67 const char *name = luaL_checkstring(L, 1);
83c98d82
DE
68 const char *configpath = NULL;
69 int argc = lua_gettop(L);
70
71 if (argc > 1)
72 configpath = luaL_checkstring(L, 2);
f080ffd7 73
83c98d82 74 c = lxc_container_new(name, configpath);
f080ffd7
DE
75 if (c) {
76 lua_boxpointer(L, c);
77 luaL_getmetatable(L, CONTAINER_TYPENAME);
78 lua_setmetatable(L, -2);
79 } else {
80 lua_pushnil(L);
81 }
82 return 1;
83}
84
85static int container_gc(lua_State *L)
86{
87 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
88
89 /* XXX what to do if this fails? */
90 lxc_container_put(c);
91 return 0;
92}
93
94static int container_config_file_name(lua_State *L)
95{
96 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
97 char *config_file_name;
98
99 config_file_name = c->config_file_name(c);
100 lua_pushstring(L, config_file_name);
101 free(config_file_name);
102 return 1;
103}
104
105static int container_defined(lua_State *L)
106{
107 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
108
109 lua_pushboolean(L, !!c->is_defined(c));
110 return 1;
111}
112
113static int container_name(lua_State *L)
114{
115 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
116
117 lua_pushstring(L, c->name);
118 return 1;
119}
120
121static int container_create(lua_State *L)
122{
123 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
124 char *template_name = strdupa(luaL_checkstring(L, 2));
125 int argc = lua_gettop(L);
126 char **argv;
127 int i;
128
129 argv = alloca((argc+1) * sizeof(char *));
130 for (i = 0; i < argc-2; i++)
131 argv[i] = strdupa(luaL_checkstring(L, i+3));
132 argv[i] = NULL;
133
dc23c1c8 134 lua_pushboolean(L, !!c->create(c, template_name, NULL, NULL, 0, argv));
f080ffd7
DE
135 return 1;
136}
137
138static int container_destroy(lua_State *L)
139{
140 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
141
142 lua_pushboolean(L, !!c->destroy(c));
143 return 1;
144}
145
146/* container state */
147static int container_start(lua_State *L)
148{
149 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
150 int argc = lua_gettop(L);
151 char **argv = NULL;
152 int i,j;
153 int useinit = 0;
154
155 if (argc > 1) {
156 argv = alloca((argc+1) * sizeof(char *));
157 for (i = 0, j = 0; i < argc-1; i++) {
158 const char *arg = luaL_checkstring(L, i+2);
159
160 if (!strcmp(arg, "useinit"))
161 useinit = 1;
162 else
163 argv[j++] = strdupa(arg);
164 }
165 argv[j] = NULL;
166 }
167
540f932a 168 c->want_daemonize(c, true);
f080ffd7
DE
169 lua_pushboolean(L, !!c->start(c, useinit, argv));
170 return 1;
171}
172
173static int container_stop(lua_State *L)
174{
175 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
176
177 lua_pushboolean(L, !!c->stop(c));
178 return 1;
179}
180
181static int container_shutdown(lua_State *L)
182{
183 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
184 int timeout = luaL_checkinteger(L, 2);
185
186 lua_pushboolean(L, !!c->shutdown(c, timeout));
187 return 1;
188}
189
190static int container_wait(lua_State *L)
191{
192 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
193 const char *state = luaL_checkstring(L, 2);
194 int timeout = luaL_checkinteger(L, 3);
195
196 lua_pushboolean(L, !!c->wait(c, state, timeout));
197 return 1;
198}
199
9bfdc223
AJM
200static int container_rename(lua_State *L)
201{
202 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
203 const char *new_name;
204 int argc = lua_gettop(L);
205
206 if (argc > 1) {
207 new_name = luaL_checkstring(L, 2);
208 lua_pushboolean(L, !!c->rename(c, new_name));
209 } else
210 lua_pushnil(L);
211 return 1;
212}
213
f080ffd7
DE
214static int container_freeze(lua_State *L)
215{
216 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
217
218 lua_pushboolean(L, !!c->freeze(c));
219 return 1;
220}
221
222static int container_unfreeze(lua_State *L)
223{
224 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
225
226 lua_pushboolean(L, !!c->unfreeze(c));
227 return 1;
228}
229
230static int container_running(lua_State *L)
231{
232 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
233
234 lua_pushboolean(L, !!c->is_running(c));
235 return 1;
236}
237
238static int container_state(lua_State *L)
239{
240 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
241
242 lua_pushstring(L, c->state(c));
243 return 1;
244}
245
246static int container_init_pid(lua_State *L)
247{
248 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
249
250 lua_pushinteger(L, c->init_pid(c));
251 return 1;
252}
253
254/* configuration file methods */
255static int container_load_config(lua_State *L)
256{
257 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
258 int arg_cnt = lua_gettop(L);
259 const char *alt_path = NULL;
260
261 if (arg_cnt > 1)
262 alt_path = luaL_checkstring(L, 2);
263
264 lua_pushboolean(L, !!c->load_config(c, alt_path));
265 return 1;
266}
267
268static int container_save_config(lua_State *L)
269{
270 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
271 int arg_cnt = lua_gettop(L);
272 const char *alt_path = NULL;
273
274 if (arg_cnt > 1)
275 alt_path = luaL_checkstring(L, 2);
276
277 lua_pushboolean(L, !!c->save_config(c, alt_path));
278 return 1;
279}
280
83c98d82
DE
281static int container_get_config_path(lua_State *L)
282{
283 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
284 const char *config_path;
285
286 config_path = c->get_config_path(c);
287 lua_pushstring(L, config_path);
288 return 1;
289}
290
291static int container_set_config_path(lua_State *L)
292{
293 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
294 const char *config_path = luaL_checkstring(L, 2);
295
296 lua_pushboolean(L, !!c->set_config_path(c, config_path));
297 return 1;
298}
299
f080ffd7
DE
300static int container_clear_config_item(lua_State *L)
301{
302 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
303 const char *key = luaL_checkstring(L, 2);
304
305 lua_pushboolean(L, !!c->clear_config_item(c, key));
306 return 1;
307}
308
80ee2228
DE
309static int container_get_cgroup_item(lua_State *L)
310{
311 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
312 const char *key = luaL_checkstring(L, 2);
313 int len;
314 char *value;
315
316 len = c->get_cgroup_item(c, key, NULL, 0);
317 if (len <= 0)
318 goto not_found;
319
320 value = alloca(sizeof(char)*len + 1);
321 if (c->get_cgroup_item(c, key, value, len + 1) != len)
322 goto not_found;
323
324 lua_pushstring(L, value);
325 return 1;
326
327not_found:
328 lua_pushnil(L);
329 return 1;
330}
331
f080ffd7
DE
332static int container_get_config_item(lua_State *L)
333{
334 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
335 const char *key = luaL_checkstring(L, 2);
336 int len;
337 char *value;
338
339 len = c->get_config_item(c, key, NULL, 0);
340 if (len <= 0)
341 goto not_found;
342
343 value = alloca(sizeof(char)*len + 1);
344 if (c->get_config_item(c, key, value, len + 1) != len)
345 goto not_found;
346
347 lua_pushstring(L, value);
348 return 1;
349
350not_found:
351 lua_pushnil(L);
352 return 1;
353}
354
80ee2228
DE
355static int container_set_cgroup_item(lua_State *L)
356{
357 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
358 const char *key = luaL_checkstring(L, 2);
359 const char *value = luaL_checkstring(L, 3);
360
361 lua_pushboolean(L, !!c->set_cgroup_item(c, key, value));
362 return 1;
363}
364
f080ffd7
DE
365static int container_set_config_item(lua_State *L)
366{
367 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
368 const char *key = luaL_checkstring(L, 2);
369 const char *value = luaL_checkstring(L, 3);
370
371 lua_pushboolean(L, !!c->set_config_item(c, key, value));
372 return 1;
373}
374
375static int container_get_keys(lua_State *L)
376{
377 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
378 const char *key = NULL;
379 int len;
380 char *value;
381 int arg_cnt = lua_gettop(L);
382
383 if (arg_cnt > 1)
384 key = luaL_checkstring(L, 2);
385
386 len = c->get_keys(c, key, NULL, 0);
387 if (len <= 0)
388 goto not_found;
389
390 value = alloca(sizeof(char)*len + 1);
391 if (c->get_keys(c, key, value, len + 1) != len)
392 goto not_found;
393
394 lua_pushstring(L, value);
395 return 1;
396
397not_found:
398 lua_pushnil(L);
399 return 1;
400}
401
ed70d078
P
402static int container_attach(lua_State *L)
403{
404 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
405 int argc = lua_gettop(L);
406 char **argv = NULL;
2f64d631 407 int i;
ed70d078
P
408
409 if (argc > 1) {
410 argv = alloca((argc+1) * sizeof(char *));
2f64d631 411 for (i = 0; i < argc-1; i++) {
412 const char *arg = luaL_checkstring(L, i+2);
413 argv[i] = strdupa(arg);
ed70d078 414 }
2f64d631 415 argv[i] = NULL;
416 }
417 else
418 {
419 lua_pushnil(L);
420 return 1;
421 }
ed70d078 422
4086cea5 423 lua_pushboolean(L, !(c->attach_run_wait(c, NULL, argv[0], (const char**)argv)));
ed70d078
P
424 return 1;
425}
426
9bfdc223
AJM
427static int container_get_interfaces(lua_State *L)
428{
429 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
430 char **ifaces;
431 int i;
432
433 ifaces = c->get_interfaces(c);
434
435 if (!ifaces){
436 lua_pushnil(L);
437 return 1;
438 }
439
440 for (i = 0; ifaces[i]; i++);
441
442 /* protect LUA stack form overflow */
443 if (i > MAXVARS || !lua_checkstack(L, i)){
444 for (i = 0; ifaces[i]; i++)
445 free(ifaces[i]);
446 lua_pushnil(L);
447 return 1;
448 }
449 for (i = 0; ifaces[i]; i++){
450 lua_pushstring(L, ifaces[i]);
451 free(ifaces[i]);
452 }
453 return i;
454}
455
456static int container_get_ips(lua_State *L)
457{
458 struct lxc_container *c = lua_unboxpointer(L, 1, CONTAINER_TYPENAME);
459 int argc = lua_gettop(L);
460 char **addresses;
461 char *iface = NULL, *family = NULL;
462 int i, scope = 0;
463
464 if (argc > 1)
465 iface = (char *)luaL_checkstring(L, 2);
466 if (argc > 2)
467 family = (char *)luaL_checkstring(L, 3);
468 if (argc > 3)
469 scope = luaL_checkinteger(L, 4);
470
471 addresses = c->get_ips(c, iface, family, scope);
472
473 if (!addresses){
474 lua_pushnil(L);
475 return 1;
476 }
477
478 for (i = 0; addresses[i]; i++);
479
480 /* protect LUA stack form overflow */
481 if (i > MAXVARS || !lua_checkstack(L, i)){
482 for (i = 0; addresses[i]; i++)
483 free(addresses[i]);
484 lua_pushnil(L);
485 return 1;
486 }
487 for (i = 0; addresses[i]; i++){
488 lua_pushstring(L, addresses[i]);
489 free(addresses[i]);
490 }
491 return i;
492}
493
f080ffd7
DE
494static luaL_Reg lxc_container_methods[] =
495{
ed70d078 496 {"attach", container_attach},
f080ffd7
DE
497 {"create", container_create},
498 {"defined", container_defined},
499 {"destroy", container_destroy},
500 {"init_pid", container_init_pid},
501 {"name", container_name},
502 {"running", container_running},
503 {"state", container_state},
504 {"freeze", container_freeze},
505 {"unfreeze", container_unfreeze},
506 {"start", container_start},
507 {"stop", container_stop},
508 {"shutdown", container_shutdown},
509 {"wait", container_wait},
9bfdc223 510 {"rename", container_rename},
f080ffd7
DE
511
512 {"config_file_name", container_config_file_name},
513 {"load_config", container_load_config},
514 {"save_config", container_save_config},
80ee2228
DE
515 {"get_cgroup_item", container_get_cgroup_item},
516 {"set_cgroup_item", container_set_cgroup_item},
83c98d82
DE
517 {"get_config_path", container_get_config_path},
518 {"set_config_path", container_set_config_path},
f080ffd7
DE
519 {"get_config_item", container_get_config_item},
520 {"set_config_item", container_set_config_item},
521 {"clear_config_item", container_clear_config_item},
522 {"get_keys", container_get_keys},
9bfdc223
AJM
523 {"get_interfaces", container_get_interfaces},
524 {"get_ips", container_get_ips},
f080ffd7
DE
525 {NULL, NULL}
526};
527
528static int lxc_version_get(lua_State *L) {
529 lua_pushstring(L, VERSION);
530 return 1;
531}
532
83c98d82 533static int lxc_default_config_path_get(lua_State *L) {
593e8478 534 const char *lxcpath = lxc_get_global_config_item("lxc.lxcpath");
2a59a681 535
2a59a681 536 lua_pushstring(L, lxcpath);
f080ffd7
DE
537 return 1;
538}
539
8585f204
DE
540static int cmd_get_config_item(lua_State *L)
541{
542 int arg_cnt = lua_gettop(L);
543 const char *name = luaL_checkstring(L, 1);
544 const char *key = luaL_checkstring(L, 2);
545 const char *lxcpath = NULL;
546 char *value;
547
548 if (arg_cnt > 2)
549 lxcpath = luaL_checkstring(L, 3);
550
551 value = lxc_cmd_get_config_item(name, key, lxcpath);
552 if (!value)
553 goto not_found;
554
555 lua_pushstring(L, value);
556 return 1;
557
558not_found:
559 lua_pushnil(L);
560 return 1;
561}
562
ac825528
NC
563/* utility functions */
564static int lxc_util_usleep(lua_State *L) {
565 usleep((useconds_t)luaL_checkunsigned(L, 1));
566 return 0;
567}
568
c25c2970
NC
569static int lxc_util_dirname(lua_State *L) {
570 char *path = strdupa(luaL_checkstring(L, 1));
571 lua_pushstring(L, dirname(path));
572 return 1;
573}
574
f080ffd7
DE
575static luaL_Reg lxc_lib_methods[] = {
576 {"version_get", lxc_version_get},
83c98d82 577 {"default_config_path_get", lxc_default_config_path_get},
8585f204 578 {"cmd_get_config_item", cmd_get_config_item},
f080ffd7 579 {"container_new", container_new},
ac825528 580 {"usleep", lxc_util_usleep},
c25c2970 581 {"dirname", lxc_util_dirname},
f080ffd7
DE
582 {NULL, NULL}
583};
584
585static int lxc_lib_uninit(lua_State *L) {
586 (void) L;
587 /* this is where we would fini liblxc.so if we needed to */
588 return 0;
589}
590
591LUALIB_API int luaopen_lxc_core(lua_State *L) {
592 /* this is where we would initialize liblxc.so if we needed to */
593
44a80d67 594 luaL_newlib(L, lxc_lib_methods);
f080ffd7
DE
595
596 lua_newuserdata(L, 0);
597 lua_newtable(L); /* metatable */
598 lua_pushvalue(L, -1);
599 lua_pushliteral(L, "__gc");
600 lua_pushcfunction(L, lxc_lib_uninit);
601 lua_rawset(L, -3);
602 lua_setmetatable(L, -3);
603 lua_rawset(L, -3);
604
605 luaL_newmetatable(L, CONTAINER_TYPENAME);
44a80d67 606 luaL_setfuncs(L, lxc_container_methods, 0);
f080ffd7
DE
607 lua_pushvalue(L, -1); /* push metatable */
608 lua_pushstring(L, "__gc");
609 lua_pushcfunction(L, container_gc);
610 lua_settable(L, -3);
611 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
f080ffd7
DE
612 lua_pop(L, 1);
613 return 1;
614}