]> git.proxmox.com Git - mirror_lxc.git/blob - src/lua-lxc/core.c
tree-wide: cleanup
[mirror_lxc.git] / src / lua-lxc / core.c
1 /*
2 * lua-lxc: lua bindings for lxc
3 *
4 * Copyright © 2012 Oracle.
5 *
6 * Authors:
7 * Dwight Engen <dwight.engen@oracle.com>
8 *
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
22 */
23
24 #define LUA_LIB
25 #define _GNU_SOURCE
26 #include <lua.h>
27 #include <lauxlib.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <libgen.h>
32 #include <lxc/lxccontainer.h>
33 #include "lxc/commands.h"
34
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))
38 #define luaL_checkunsigned(L,n) luaL_checknumber(L,n)
39 #endif
40
41 #if LUA_VERSION_NUM >= 503
42 #ifndef luaL_checkunsigned
43 #define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n))
44 #endif
45 #endif
46
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
61 /* Max Lua arguments for function */
62 #define MAXVARS 200
63
64 static int container_new(lua_State *L)
65 {
66 struct lxc_container *c;
67 const char *name = luaL_checkstring(L, 1);
68 const char *configpath = NULL;
69 int argc = lua_gettop(L);
70
71 if (argc > 1)
72 configpath = luaL_checkstring(L, 2);
73
74 c = lxc_container_new(name, configpath);
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
85 static 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
94 static 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
105 static 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
113 static 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
121 static 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
134 lua_pushboolean(L, !!c->create(c, template_name, NULL, NULL, 0, argv));
135 return 1;
136 }
137
138 static 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 */
147 static 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
168 c->want_daemonize(c, true);
169 lua_pushboolean(L, !!c->start(c, useinit, argv));
170 return 1;
171 }
172
173 static 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
181 static 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
190 static 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
200 static 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
214 static 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
222 static 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
230 static 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
238 static 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
246 static 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 */
255 static 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
268 static 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
281 static 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
291 static 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
300 static 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
309 static 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
327 not_found:
328 lua_pushnil(L);
329 return 1;
330 }
331
332 static 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
350 not_found:
351 lua_pushnil(L);
352 return 1;
353 }
354
355 static 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
365 static 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
375 static 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
397 not_found:
398 lua_pushnil(L);
399 return 1;
400 }
401
402 static 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;
407 int i;
408
409 if (argc > 1) {
410 argv = alloca((argc+1) * sizeof(char *));
411 for (i = 0; i < argc-1; i++) {
412 const char *arg = luaL_checkstring(L, i+2);
413 argv[i] = strdupa(arg);
414 }
415 argv[i] = NULL;
416 }
417 else
418 {
419 lua_pushnil(L);
420 return 1;
421 }
422
423 lua_pushboolean(L, !(c->attach_run_wait(c, NULL, argv[0], (const char**)argv)));
424 return 1;
425 }
426
427 static 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
456 static 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
494 static luaL_Reg lxc_container_methods[] =
495 {
496 {"attach", container_attach},
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},
510 {"rename", container_rename},
511
512 {"config_file_name", container_config_file_name},
513 {"load_config", container_load_config},
514 {"save_config", container_save_config},
515 {"get_cgroup_item", container_get_cgroup_item},
516 {"set_cgroup_item", container_set_cgroup_item},
517 {"get_config_path", container_get_config_path},
518 {"set_config_path", container_set_config_path},
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},
523 {"get_interfaces", container_get_interfaces},
524 {"get_ips", container_get_ips},
525 {NULL, NULL}
526 };
527
528 static int lxc_version_get(lua_State *L) {
529 lua_pushstring(L, VERSION);
530 return 1;
531 }
532
533 static int lxc_default_config_path_get(lua_State *L) {
534 const char *lxcpath = lxc_get_global_config_item("lxc.lxcpath");
535
536 lua_pushstring(L, lxcpath);
537 return 1;
538 }
539
540 static 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
558 not_found:
559 lua_pushnil(L);
560 return 1;
561 }
562
563 /* utility functions */
564 static int lxc_util_usleep(lua_State *L) {
565 usleep((useconds_t)luaL_checkunsigned(L, 1));
566 return 0;
567 }
568
569 static 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
575 static luaL_Reg lxc_lib_methods[] = {
576 {"version_get", lxc_version_get},
577 {"default_config_path_get", lxc_default_config_path_get},
578 {"cmd_get_config_item", cmd_get_config_item},
579 {"container_new", container_new},
580 {"usleep", lxc_util_usleep},
581 {"dirname", lxc_util_dirname},
582 {NULL, NULL}
583 };
584
585 static 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
591 LUALIB_API int luaopen_lxc_core(lua_State *L) {
592 /* this is where we would initialize liblxc.so if we needed to */
593
594 luaL_newlib(L, lxc_lib_methods);
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);
606 luaL_setfuncs(L, lxc_container_methods, 0);
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 */
612 lua_pop(L, 1);
613 return 1;
614 }