From: dlezcano Date: Tue, 2 Sep 2008 09:48:12 +0000 (+0000) Subject: Added C++ compatibility, change to libtool, improve monitoring X-Git-Tag: lxc-2.1.1~3561 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=c2cc9f0a9b052563d803d3d1e685e307d1d1412b;p=mirror_lxc.git Added C++ compatibility, change to libtool, improve monitoring --- diff --git a/configure.in b/configure.in index f376a6455..7b1322c4c 100644 --- a/configure.in +++ b/configure.in @@ -11,6 +11,7 @@ AC_CANONICAL_HOST AC_PROG_RANLIB AM_PROG_CC_C_O AC_GNU_SOURCE +AC_PROG_LIBTOOL AC_CHECK_HEADERS([linux/netlink.h linux/genetlink.h],, AC_MSG_ERROR([netlink headers not found]), [[]]) AC_PROG_GCC_TRADITIONAL diff --git a/lxc.spec.in b/lxc.spec.in index ff340d097..773f73112 100644 --- a/lxc.spec.in +++ b/lxc.spec.in @@ -82,6 +82,7 @@ rm -rf %{buildroot} %files %defattr(-,root,root) %{_sysconfdir}/%{name}/* +%{_libdir}/*.so* %{_bindir}/* %files devel @@ -89,6 +90,10 @@ rm -rf %{buildroot} %{_includedir}/%{name}/* %{_libdir}/*.a +%post devel +ln -sf %{_includedir}/%{name} %{_includedir}/liblxc + + %changelog * Sun Aug 3 2008 Daniel Lezcano - Initial RPM release. diff --git a/src/liblxc/Makefile.am b/src/liblxc/Makefile.am index eeebd0864..bb548d56c 100644 --- a/src/liblxc/Makefile.am +++ b/src/liblxc/Makefile.am @@ -1,4 +1,4 @@ -lib_LIBRARIES = liblxc.a +lib_LTLIBRARIES = liblxc.la pkginclude_HEADERS = \ lxc.h \ lxc_cgroup.h \ @@ -10,16 +10,15 @@ pkginclude_HEADERS = \ lxc_state.h \ lxc_utils.h -liblxc_a_SOURCES = \ +liblxc_la_SOURCES = \ create.c \ destroy.c \ start.c \ stop.c \ execute.c \ - monitor.c \ + monitor.c monitor.h \ kill.c \ freezer.c \ - lxc_state.c lxc_state.h \ lxc_cgroup.c lxc_cgroup.h \ lxc.h \ lxc_utils.h \ @@ -34,3 +33,5 @@ liblxc_a_SOURCES = \ nl.c nl.h \ rtnl.c rtnl.h \ genl.c genl.h + +liblxc_la_LDFLAGS = -release @PACKAGE_VERSION@ \ No newline at end of file diff --git a/src/liblxc/create.c b/src/liblxc/create.c index dc3b05faa..2891eba65 100644 --- a/src/liblxc/create.c +++ b/src/liblxc/create.c @@ -116,7 +116,7 @@ int lxc_create(const char *name, struct lxc_conf *conf) goto err; } - if (mkstate(name)) { + if (lxc_mkstate(name)) { lxc_log_error("failed to create the state file for %s", name); goto err; } @@ -139,7 +139,7 @@ out: err_state: lxc_unconfigure(name); - if (rmstate(name)) + if (lxc_rmstate(name)) lxc_log_error("failed to remove state file for %s", name); err: if (remove_lxc_directory(name)) diff --git a/src/liblxc/destroy.c b/src/liblxc/destroy.c index fb08da29b..266a5ae04 100644 --- a/src/liblxc/destroy.c +++ b/src/liblxc/destroy.c @@ -94,10 +94,12 @@ int lxc_destroy(const char *name) goto out; } - if (rmstate(name)) { + if (lxc_rmstate(name)) { lxc_log_error("failed to remove state file for %s", name); goto out_lock; } + + lxc_monitor_cleanup(name); if (lxc_unconfigure(name)) { lxc_log_error("failed to cleanup %s", name); diff --git a/src/liblxc/execute.c b/src/liblxc/execute.c index 207ad3005..4bfcbcc30 100644 --- a/src/liblxc/execute.c +++ b/src/liblxc/execute.c @@ -64,10 +64,8 @@ int lxc_execute(const char *name, int argc, char *argv[], return -1; } - fcntl(lock, F_SETFD, FD_CLOEXEC); - if (lxc_setstate(name, STARTING)) { - lxc_log_error("failed to set state %s", state2str(STARTING)); + lxc_log_error("failed to set state %s", lxc_state2str(STARTING)); goto out; } @@ -117,10 +115,12 @@ int lxc_execute(const char *name, int argc, char *argv[], lxc_log_error("failed to setup the container"); goto error; } + if (mount("proc", "/proc", "proc", 0, NULL)) { - lxc_log_error("failed to mount '/proc'"); + lxc_log_syserror("failed to mount '/proc'"); goto error; } + if (mount("sysfs", "/sys", "sysfs", 0, NULL)) { lxc_log_syserror("failed to mount '/sys'"); /* continue: non fatal error until sysfs not per @@ -213,7 +213,7 @@ int lxc_execute(const char *name, int argc, char *argv[], lxc_log_warning("cgroupfs not found: cgroup disabled"); if (lxc_setstate(name, RUNNING)) { - lxc_log_error("failed to set state to %s", state2str(RUNNING)); + lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING)); goto err_state_failed; } @@ -226,7 +226,7 @@ wait_again: } if (lxc_setstate(name, STOPPING)) - lxc_log_error("failed to set state %s", state2str(STOPPING)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPING)); if (clone_flags & CLONE_NEWNET && conf_destroy_network(name)) lxc_log_error("failed to destroy the network"); @@ -234,7 +234,7 @@ wait_again: err = 0; out: if (lxc_setstate(name, STOPPED)) - lxc_log_error("failed to set state %s", state2str(STOPPED)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPED)); lxc_unlink_nsgroup(name); unlink(init); @@ -257,7 +257,7 @@ err_pipe_read: err_open: err_waitpid_failed: if (lxc_setstate(name, ABORTING)) - lxc_log_error("failed to set state %s", state2str(STOPPED)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPED)); kill(pid, SIGKILL); err_fork_ns: diff --git a/src/liblxc/lock.c b/src/liblxc/lock.c index 26b5c170b..70bdcfc23 100644 --- a/src/liblxc/lock.c +++ b/src/liblxc/lock.c @@ -42,6 +42,8 @@ int lxc_get_lock(const char *name) goto out; } + fcntl(fd, F_SETFD, FD_CLOEXEC); + if (flock(fd, LOCK_EX|LOCK_NB)) { ret = errno == EWOULDBLOCK ? 0 : -errno; close(fd); diff --git a/src/liblxc/lxc.h b/src/liblxc/lxc.h index 0369a6833..d1f027f66 100644 --- a/src/liblxc/lxc.h +++ b/src/liblxc/lxc.h @@ -23,20 +23,24 @@ #ifndef __lxc_h #define __lxc_h +#ifdef __cplusplus +extern "C" { +#endif + /** Following code is for liblxc. liblxc/lxc.h will contain exports of liblxc **/ -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #define LXCPATH "/var/lxc" #define MAXPIDLEN 20 @@ -104,12 +108,37 @@ extern int lxc_stop(const char *name); * is changed, a state data is send through a file descriptor passed to * the function with output_fd. * The function will block until the container is destroyed. - * @name : the name of the contaier + * @name : the name of the container * @output_fd : the file descriptor where to send the states * Returns 0 on success, < 0 otherwise */ extern int lxc_monitor(const char *name, int output_fd); +/* + * Open the monitoring mechanism for a specific container + * The function will return an fd corresponding to the events + * @name : the name of the container + * Returns a file descriptor on success, < 0 otherwise + */ +extern int lxc_monitor_open(const char *name); + +/* + * Read the state of the container if this one has changed + * The function will block until there is an event available + * @fd : the file descriptor provided by lxc_monitor_open + * @state : the variable which will be filled with the state + * Returns 0 if the monitored container has exited, > 0 if + * data was readen, < 0 otherwise + */ +extern int lxc_monitor_read(int fd, lxc_state_t *state); + +/* + * Close the fd associated with the monitoring + * @fd : the file descriptor provided by lxc_monitor_open + * Returns 0 on success, < 0 otherwise + */ +extern int lxc_monitor_close(int fd); + /* * Show the console of the container. * @name : the name of container @@ -220,4 +249,8 @@ extern int lxc_cgroup_get_cpuset(const char *name, long *cpumask, */ extern int lxc_cgroup_get_cpu_usage(const char *name, long long *usage); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/liblxc/lxc_cgroup.c b/src/liblxc/lxc_cgroup.c index dc185a08d..238f28523 100644 --- a/src/liblxc/lxc_cgroup.c +++ b/src/liblxc/lxc_cgroup.c @@ -101,7 +101,7 @@ int lxc_unlink_nsgroup(const char *name) return ret; } -int lxc_set_priority(const char *name, int priority) +int lxc_cgroup_set_priority(const char *name, int priority) { int fd; char *path = NULL, *prio = NULL; @@ -129,7 +129,7 @@ out: return 0; } -int lxc_get_priority(const char *name, int *priority) +int lxc_cgroup_get_priority(const char *name, int *priority) { int fd, ret = -1; char *path, prio[MAXPRIOLEN]; diff --git a/src/liblxc/lxc_list.h b/src/liblxc/lxc_list.h index c6727e95b..45c04fb1f 100644 --- a/src/liblxc/lxc_list.h +++ b/src/liblxc/lxc_list.h @@ -35,13 +35,13 @@ static inline int lxc_list_empty(struct lxc_list *list) return list == list->next; } -static inline void lxc_list_add(struct lxc_list *list, struct lxc_list *new) +static inline void lxc_list_add(struct lxc_list *head, struct lxc_list *list) { - struct lxc_list *next = list->next; - next->prev = new; - new->next = next; - new->prev = list; - list->next = new; + struct lxc_list *next = head->next; + next->prev = list; + list->next = next; + list->prev = head; + head->next = list; } static inline void lxc_list_del(struct lxc_list *list) diff --git a/src/liblxc/lxc_state.c b/src/liblxc/lxc_state.c index 86e4d9f6b..462298dc1 100644 --- a/src/liblxc/lxc_state.c +++ b/src/liblxc/lxc_state.c @@ -32,20 +32,21 @@ #include #include +#include "monitor.h" static char *strstate[] = { "STOPPED", "STARTING", "RUNNING", "STOPPING", "ABORTING", "FREEZING", "FROZEN", }; -const char *state2str(lxc_state_t state) +const char *lxc_state2str(lxc_state_t state) { if (state < STOPPED || state > MAX_STATE - 1) return NULL; return strstate[state]; } -lxc_state_t str2state(const char *state) +lxc_state_t lxc_str2state(const char *state) { int i, len; len = sizeof(strstate)/sizeof(strstate[0]); @@ -59,7 +60,7 @@ int lxc_setstate(const char *name, lxc_state_t state) { int fd, err; char file[MAXPATHLEN]; - const char *str = state2str(state); + const char *str = lxc_state2str(state); if (!str) return -1; @@ -91,6 +92,8 @@ int lxc_setstate(const char *name, lxc_state_t state) out: close(fd); + lxc_monitor_send_state(name, state); + /* let the event to be propagated, crappy but that works, * otherwise the events will be folded into only one event, * and I want to have them to be one by one in order @@ -101,7 +104,7 @@ out: return -err; } -int mkstate(const char *name) +int lxc_mkstate(const char *name) { int fd; char file[MAXPATHLEN]; @@ -116,7 +119,7 @@ int mkstate(const char *name) return 0; } -int rmstate(const char *name) +int lxc_rmstate(const char *name) { char file[MAXPATHLEN]; snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name); @@ -152,7 +155,7 @@ lxc_state_t lxc_getstate(const char *name) file[err] = '\0'; close(fd); - return str2state(file); + return lxc_str2state(file); } static int freezer_state(const char *name) @@ -166,7 +169,7 @@ static int freezer_state(const char *name) LXCPATH "/%s/freezer.freeze", name); file = fopen(freezer, "r"); - if (file < 0) { + if (!file) { lxc_log_syserror("failed to open %s", freezer); return -1; } @@ -179,7 +182,7 @@ static int freezer_state(const char *name) return -1; } - return str2state(status); + return lxc_str2state(status); } lxc_state_t lxc_state(const char *name) diff --git a/src/liblxc/lxc_state.h b/src/liblxc/lxc_state.h index 27f4f5e02..871d1a8d5 100644 --- a/src/liblxc/lxc_state.h +++ b/src/liblxc/lxc_state.h @@ -28,11 +28,12 @@ typedef enum { ABORTING, FREEZING, FROZEN, MAX_STATE, } lxc_state_t; -extern const char *state2str(lxc_state_t state); -extern lxc_state_t str2state(const char *state); -extern int mkstate(const char *name); -extern int rmstate(const char *name); +extern int lxc_mkstate(const char *name); +extern int lxc_rmstate(const char *name); extern int lxc_setstate(const char *name, lxc_state_t state); extern lxc_state_t lxc_getstate(const char *name); +extern lxc_state_t lxc_str2state(const char *state); +extern const char *lxc_state2str(lxc_state_t state); + #endif diff --git a/src/liblxc/monitor.c b/src/liblxc/monitor.c index ce5fd19d2..3f247dd19 100644 --- a/src/liblxc/monitor.c +++ b/src/liblxc/monitor.c @@ -24,16 +24,22 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include - #include +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + int lxc_monitor(const char *name, int output_fd) { char path[MAXPATHLEN]; @@ -93,3 +99,72 @@ out: close(nfd); return err; } + +void lxc_monitor_send_state(const char *name, lxc_state_t state) +{ + int fd; + struct sockaddr_un addr; + + fd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) + lxc_log_syserror("failed to create notification socket"); + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name); + + sendto(fd, &state, sizeof(state), 0, + (const struct sockaddr *)&addr, sizeof(addr)); + + close(fd); +} + +void lxc_monitor_cleanup(const char *name) +{ + char path[UNIX_PATH_MAX]; + snprintf(path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name); + unlink(path); +} + +int lxc_monitor_open(const char *name) +{ + int fd; + struct sockaddr_un addr; + + fd = socket(PF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + lxc_log_syserror("failed to create notification socket"); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name); + unlink(addr.sun_path); + + if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) { + lxc_log_syserror("failed to bind to '%s'", addr.sun_path); + return -1; + } + + return fd; +} + +int lxc_monitor_read(int fd, lxc_state_t *state) +{ + int ret; + + ret = recv(fd, state, sizeof(*state), 0); + if (ret < 0) { + lxc_log_syserror("failed to received state"); + return -1; + } + + return ret; +} + +int lxc_monitor_close(int fd) +{ + return close(fd); +} diff --git a/src/liblxc/start.c b/src/liblxc/start.c index 55526645c..d0252c587 100644 --- a/src/liblxc/start.c +++ b/src/liblxc/start.c @@ -69,7 +69,7 @@ int lxc_start(const char *name, int argc, char *argv[], /* Begin the set the state to STARTING*/ if (lxc_setstate(name, STARTING)) { - lxc_log_error("failed to set state %s", state2str(STARTING)); + lxc_log_error("failed to set state %s", lxc_state2str(STARTING)); goto out; } @@ -195,7 +195,7 @@ int lxc_start(const char *name, int argc, char *argv[], lxc_log_warning("cgroupfs not found: cgroup disabled"); if (lxc_setstate(name, RUNNING)) { - lxc_log_error("failed to set state to %s", state2str(RUNNING)); + lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING)); goto err_state_failed; } @@ -208,7 +208,7 @@ wait_again: } if (lxc_setstate(name, STOPPING)) - lxc_log_error("failed to set state %s", state2str(STOPPING)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPING)); if (clone_flags & CLONE_NEWNET && conf_destroy_network(name)) lxc_log_error("failed to destroy the network"); @@ -216,7 +216,7 @@ wait_again: err = 0; out: if (lxc_setstate(name, STOPPED)) - lxc_log_error("failed to set state %s", state2str(STOPPED)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPED)); lxc_unlink_nsgroup(name); unlink(init); @@ -239,7 +239,7 @@ err_create_network: err_pipe_read: err_waitpid_failed: if (lxc_setstate(name, ABORTING)) - lxc_log_error("failed to set state %s", state2str(STOPPED)); + lxc_log_error("failed to set state %s", lxc_state2str(STOPPED)); kill(pid, SIGKILL); err_fork_ns: diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am index c57e76c89..259ae9d11 100644 --- a/src/lxc/Makefile.am +++ b/src/lxc/Makefile.am @@ -17,50 +17,50 @@ bin_PROGRAMS = \ lxc-unfreeze \ lxc-priority -lxc_create_SOURCES = lxc_create.c config.c config.h +lxc_create_SOURCES = lxc_create.c lxc_config.c lxc_config.h lxc_create_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_destroy_SOURCES = lxc_destroy.c lxc_destroy_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_start_SOURCES = lxc_start.c lxc_start_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_stop_SOURCES = lxc_stop.c lxc_stop_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la -lxc_execute_SOURCES = lxc_execute.c config.c +lxc_execute_SOURCES = lxc_execute.c lxc_execute_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_monitor_SOURCES = lxc_monitor.c lxc_monitor_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_console_SOURCES = lxc_console.c lxc_console_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_state_SOURCES = lxc_state.c lxc_state_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_kill_SOURCES = lxc_kill.c lxc_kill_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_freeze_SOURCES = lxc_freeze.c lxc_freeze_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_unfreeze_SOURCES = lxc_unfreeze.c lxc_unfreeze_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_priority_SOURCES = lxc_priority.c lxc_priority_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la diff --git a/src/lxc/lxc_config.c b/src/lxc/lxc_config.c new file mode 100644 index 000000000..ae1338b83 --- /dev/null +++ b/src/lxc/lxc_config.c @@ -0,0 +1,546 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef int (*file_cb)(char* buffer, void *data); +typedef int (*config_cb)(char *value, struct lxc_conf *lxc_conf); + +static int config_mount(char *, struct lxc_conf *); +static int config_chroot(char *, struct lxc_conf *); +static int config_utsname(char *, struct lxc_conf *); +static int config_network_type(char *, struct lxc_conf *); +static int config_network_flags(char *, struct lxc_conf *); +static int config_network_link(char *, struct lxc_conf *); +static int config_network_name(char *, struct lxc_conf *); +static int config_network_hwaddr(char *, struct lxc_conf *); +static int config_network_ipv4(char *, struct lxc_conf *); +static int config_network_ipv6(char *, struct lxc_conf *); + +struct config { + char *name; + int type; + config_cb cb; +}; + +enum { MOUNT, CHROOT, UTSNAME, NETTYPE, NETFLAGS, NETLINK, + NETNAME, NETHWADDR, NETIPV4, NETIPV6 }; + +struct config config[] = { + { "lxc.mount", MOUNT, config_mount }, + { "lxc.chroot", CHROOT, config_chroot }, + { "lxc.utsname", UTSNAME, config_utsname }, + { "lxc.network.type", NETTYPE, config_network_type }, + { "lxc.network.flags", NETFLAGS, config_network_flags }, + { "lxc.network.link", NETLINK, config_network_link }, + { "lxc.network.name", NETNAME, config_network_name }, + { "lxc.network.hwaddr", NETHWADDR, config_network_hwaddr }, + { "lxc.network.ipv4", NETIPV4, config_network_ipv4 }, + { "lxc.network.ipv6", NETIPV6, config_network_ipv6 }, +}; + +static const size_t config_size = sizeof(config)/sizeof(struct config); + +static struct config *getconfig(const char *key) +{ + int i; + + for (i = 0; i < config_size; i++) + if (!strncmp(config[i].name, key, + strlen(config[i].name))) + return &config[i]; + return NULL; +} + +static int is_line_empty(char *line) +{ + int i; + size_t len = strlen(line); + + for (i = 0; i < len; i++) + if (line[i] != ' ' && line[i] != '\t' && + line[i] != '\n' && line[i] != '\r' && + line[i] != '\f' && line[i] != '\0') + return 0; + return 1; +} + +static int char_left_gc(char *buffer, size_t len) +{ + int i; + for (i = 0; i < len; i++) { + if (buffer[i] == ' ' || + buffer[i] == '\t') + continue; + return i; + } + return 0; +} + +static int char_right_gc(char *buffer, size_t len) +{ + int i; + for (i = len - 1; i >= 0; i--) { + if (buffer[i] == ' ' || + buffer[i] == '\t' || + buffer[i] == '\n' || + buffer[i] == '\0') + continue; + return i + 1; + } + return 0; +} + +static int config_network_type(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + struct lxc_list *list; + struct lxc_list *ndlist; + + network = malloc(sizeof(*network)); + if (!network) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + lxc_list_init(&network->netdev); + + netdev = malloc(sizeof(*netdev)); + if (!netdev) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + lxc_list_init(&netdev->ipv4); + lxc_list_init(&netdev->ipv6); + lxc_list_init(&netdev->route4); + lxc_list_init(&netdev->route6); + + ndlist = malloc(sizeof(*ndlist)); + if (!ndlist) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + ndlist->elem = netdev; + + lxc_list_add(&network->netdev, ndlist); + + list = malloc(sizeof(*list)); + if (!list) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + lxc_list_init(list); + list->elem = network; + + lxc_list_add(networks, list); + + if (!strcmp(value, "veth")) + network->type = VETH; + else if (!strcmp(value, "macvlan")) + network->type = MACVLAN; + else if (!strcmp(value, "phys")) + network->type = PHYS; + else { + lxc_log_error("invalid network type %s", value); + return -1; + } + return 0; +} + +static int config_network_flags(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for '%s' option", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for '%s' option", value); + return -1; + } + + netdev = lxc_list_first_elem(&network->netdev); + netdev->flags |= IFF_UP; + return 0; +} + +static int config_network_link(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for %s", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for %s", value); + return -1; + } + + if (strlen(value) > IFNAMSIZ) { + lxc_log_error("invalid interface name: %s", value); + return -1; + } + + netdev = lxc_list_first_elem(&network->netdev); + netdev->ifname = strdup(value); + return 0; +} + +static int config_network_name(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for %s", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for %s", value); + return -1; + } + + if (strlen(value) > IFNAMSIZ) { + lxc_log_error("invalid interface name: %s", value); + return -1; + } + + netdev = lxc_list_first_elem(&network->netdev); + netdev->newname = strdup(value); + return 0; +} + +static int config_network_hwaddr(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for %s", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for %s", value); + return -1; + } + + netdev = lxc_list_first_elem(&network->netdev); + netdev->hwaddr = strdup(value); + return 0; +} + +static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_inetdev *inetdev; + struct lxc_netdev *netdev; + struct lxc_list *list; + char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for '%s'", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for '%s'", value); + return -1; + } + + netdev = lxc_list_first_elem(&network->netdev); + if (!netdev) { + lxc_log_error("no netdev defined for '%s'", value); + } + + inetdev = malloc(sizeof(*inetdev)); + if (!inetdev) { + lxc_log_syserror("failed to allocate ipv4 address"); + return -1; + } + memset(inetdev, 0, sizeof(*inetdev)); + + list = malloc(sizeof(*list)); + if (!list) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + lxc_list_init(list); + list->elem = inetdev; + + addr = value; + + cursor = strstr(addr, " "); + if (cursor) { + *cursor = '\0'; + bcast = cursor + 1; + } + + slash = strstr(addr, "/"); + if (slash) { + *slash = '\0'; + prefix = slash + 1; + } + + if (!addr) { + lxc_log_error("no address specified"); + return -1; + } + + if (!inet_pton(AF_INET, addr, &inetdev->addr)) { + lxc_log_syserror("invalid ipv4 address: %s", value); + return -1; + } + + if (bcast) + if (!inet_pton(AF_INET, bcast, &inetdev->bcast)) { + lxc_log_syserror("invalid ipv4 address: %s", value); + return -1; + } + + if (prefix) + inetdev->prefix = atoi(prefix); + + lxc_list_add(&netdev->ipv4, list); + + return 0; +} + +static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf) +{ + struct lxc_list *networks = &lxc_conf->networks; + struct lxc_network *network; + struct lxc_netdev *netdev; + struct lxc_inet6dev *inet6dev; + struct lxc_list *list; + char *slash; + char *netmask; + + if (lxc_list_empty(networks)) { + lxc_log_error("network is not created for %s", value); + return -1; + } + + network = lxc_list_first_elem(networks); + if (!network) { + lxc_log_error("no network defined for %s", value); + return -1; + } + + inet6dev = malloc(sizeof(*inet6dev)); + if (!inet6dev) { + lxc_log_syserror("failed to allocate ipv6 address"); + return -1; + } + memset(inet6dev, 0, sizeof(*inet6dev)); + + list = malloc(sizeof(*list)); + if (!list) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + lxc_list_init(list); + list->elem = inet6dev; + + slash = strstr(value, "/"); + if (slash) { + *slash = '\0'; + netmask = slash + 1; + inet6dev->prefix = atoi(netmask); + } + + if (!inet_pton(AF_INET6, value, &inet6dev->addr)) { + lxc_log_syserror("invalid ipv6 address: %s", value); + return -1; + } + + + netdev = lxc_list_first_elem(&network->netdev); + lxc_list_add(&netdev->ipv6, list); + + return 0; +} + +static int config_mount(char *value, struct lxc_conf *lxc_conf) +{ + if (strlen(value) >= MAXPATHLEN) { + lxc_log_error("%s path is too long", value); + return -1; + } + + lxc_conf->fstab = strdup(value); + if (!lxc_conf->fstab) { + lxc_log_syserror("failed to duplicate string %s", value); + return -1; + } + + return 0; +} + +static int config_chroot(char *value, struct lxc_conf *lxc_conf) +{ + if (strlen(value) >= MAXPATHLEN) { + lxc_log_error("%s path is too long", value); + return -1; + } + + lxc_conf->chroot = strdup(value); + if (!lxc_conf->chroot) { + lxc_log_syserror("failed to duplicate string %s", value); + return -1; + } + + return 0; +} + +static int config_utsname(char *value, struct lxc_conf *lxc_conf) +{ + struct utsname *utsname; + + utsname = malloc(sizeof(*utsname)); + if (!utsname) { + lxc_log_syserror("failed to allocate memory"); + return -1; + } + + if (strlen(value) >= sizeof(utsname->nodename)) { + lxc_log_error("node name '%s' is too long", + utsname->nodename); + return -1; + } + + strcpy(utsname->nodename, value); + lxc_conf->utsname = utsname; + + return 0; +} + +static int parse_line(char *buffer, void *data) +{ + struct config *config; + char *dot; + char *key; + char *value; + + if (is_line_empty(buffer)) + return 0; + + buffer += char_left_gc(buffer, strlen(buffer)); + if (buffer[0] == '#') + return 0; + + dot = strstr(buffer, "="); + if (!dot) { + lxc_log_error("invalid configuration line: %s", buffer); + return -1; + } + + *dot = '\0'; + value = dot + 1; + + key = buffer; + key[char_right_gc(key, strlen(key))] = '\0'; + + value += char_left_gc(value, strlen(value)); + value[char_right_gc(value, strlen(value))] = '\0'; + + config = getconfig(key); + if (!config) { + lxc_log_error("unknow key %s", key); + return -1; + } + + return config->cb(value, data); +} + +static int file_for_each_line(const char *file, file_cb callback, void *data) +{ + char buffer[MAXPATHLEN]; + size_t len = sizeof(buffer); + FILE *f; + int err = -1; + + f = fopen(file, "r"); + if (!f) { + lxc_log_syserror("failed to open %s", file); + return -1; + } + + while (fgets(buffer, len, f)) + if (callback(buffer, data)) + goto out; + err = 0; +out: + fclose(f); + return err; +} + +int lxc_config_read(const char *file, struct lxc_conf *conf) +{ + return file_for_each_line(file, parse_line, conf); +} + +int lxc_config_init(struct lxc_conf *conf) +{ + conf->chroot = NULL; + conf->fstab = NULL; + conf->utsname = NULL; + conf->cgroup = NULL; + lxc_list_init(&conf->networks); + return 0; +} diff --git a/src/lxc/lxc_config.h b/src/lxc/lxc_config.h new file mode 100644 index 000000000..f81217be0 --- /dev/null +++ b/src/lxc/lxc_config.h @@ -0,0 +1,28 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +extern int lxc_config_init(struct lxc_conf *conf); +extern int lxc_config_read(const char *file, struct lxc_conf *conf); + + + diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c index 5f9f7205b..c34b4897d 100644 --- a/src/lxc/lxc_create.c +++ b/src/lxc/lxc_create.c @@ -32,8 +32,7 @@ #include #include - -#include "config.h" +#include "lxc_config.h" void usage(char *cmd) { @@ -63,12 +62,12 @@ int main(int argc, char *argv[]) if (!name || !file) usage(argv[0]); - if (config_init(&lxc_conf)) { + if (lxc_config_init(&lxc_conf)) { fprintf(stderr, "failed to initialize the configuration\n"); return 1; } - if (config_read(file, &lxc_conf)) { + if (lxc_config_read(file, &lxc_conf)) { fprintf(stderr, "invalid configuration file\n"); return 1; } diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index b844f6124..3e1066c18 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -90,7 +90,7 @@ int main(int argc, char *argv[]) } printf("container has changed the state to %d - %s\n", - state, state2str(state)); + state, lxc_state2str(state)); } return 0; } diff --git a/src/lxc/lxc_priority.c b/src/lxc/lxc_priority.c index 9b1c5ccee..a1efe5fdb 100644 --- a/src/lxc/lxc_priority.c +++ b/src/lxc/lxc_priority.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -58,7 +59,7 @@ int main(int argc, char *argv[]) usage(argv[0]); if (!priority) { - if (lxc_get_priority(name, &prio)) { + if (lxc_cgroup_get_priority(name, &prio)) { fprintf(stderr, "failed to retrieve the priority of '%s'\n", name); return 1; } @@ -68,7 +69,7 @@ int main(int argc, char *argv[]) } prio = atoi(priority); - if (lxc_set_priority(name, prio)) { + if (lxc_cgroup_set_priority(name, prio)) { fprintf(stderr, "failed to assign priority %d to of '%s'", prio, name); return 1; diff --git a/src/lxc/lxc_state.c b/src/lxc/lxc_state.c index abb6b3c92..8939405fe 100644 --- a/src/lxc/lxc_state.c +++ b/src/lxc/lxc_state.c @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) return 1; } - printf("'%s' is %s\n", name, state2str(state)); + printf("'%s' is %s\n", name, lxc_state2str(state)); return 0; } diff --git a/test/Makefile.am b/test/Makefile.am index cc6faaaf2..01b9866db 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -18,74 +18,79 @@ noinst_PROGRAMS = \ lxc_start \ lxc_stop \ lxc_monitor \ + lxc_low_monitor \ lxc_state tst_list_SOURCES = tst_list.c tst_list_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la confile_SOURCES = confile.c confile_LDADD = \ - $(top_builddir)/src/lxc/config.o \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/lxc/lxc_config.o \ + $(top_builddir)/src/liblxc/liblxc.la conf_SOURCES = conf.c conf_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la movedev_SOURCES = movedev.c movedev_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la dev_SOURCES = dev.c dev_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la forward_SOURCES = forward.c forward_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la proxy_SOURCES = proxy.c proxy_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la veth_SOURCES = veth.c veth_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la macvlan_SOURCES = macvlan.c macvlan_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la ipv4_add_SOURCES = ipv4_add.c ipv4_add_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la ipv6_add_SOURCES = ipv6_add.c ipv6_add_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_create_SOURCES = lxc_create.c lxc_create_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_destroy_SOURCES = lxc_destroy.c lxc_destroy_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_start_SOURCES = lxc_start.c lxc_start_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_stop_SOURCES = lxc_stop.c lxc_stop_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la lxc_monitor_SOURCES = lxc_monitor.c lxc_monitor_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la + +lxc_low_monitor_SOURCES = lxc_low_monitor.c +lxc_low_monitor_LDADD = \ + $(top_builddir)/src/liblxc/liblxc.la lxc_state_SOURCES = lxc_state.c lxc_state_LDADD = \ - $(top_builddir)/src/liblxc/liblxc.a + $(top_builddir)/src/liblxc/liblxc.la diff --git a/test/confile.c b/test/confile.c index 53a6f08ec..34f597b0d 100644 --- a/test/confile.c +++ b/test/confile.c @@ -32,7 +32,7 @@ #include -#include "../src/lxc/config.h" +#include "../src/lxc/lxc_config.h" static void usage(const char *cmd) { @@ -60,12 +60,12 @@ int main(int argc, char *argv[]) if (!file || !name) usage(argv[0]); - if (config_init(&lxc_conf)) { + if (lxc_config_init(&lxc_conf)) { fprintf(stderr, "failed to initialize configuration structure\n"); return 1; } - if (config_read(file, &lxc_conf)) { + if (lxc_config_read(file, &lxc_conf)) { fprintf(stderr, "failed to read configuration\n"); return 1; } diff --git a/test/lxc_low_monitor.c b/test/lxc_low_monitor.c new file mode 100644 index 000000000..41db55338 --- /dev/null +++ b/test/lxc_low_monitor.c @@ -0,0 +1,65 @@ +/* + * lxc: linux Container library + * + * (C) Copyright IBM Corp. 2007, 2008 + * + * Authors: + * Daniel Lezcano + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include + +void usage(char *cmd) +{ + fprintf(stderr, "%s \n", basename(cmd)); + fprintf(stderr, "\t -n : name of the container\n"); + _exit(1); +} + +int main(int argc, char *argv[]) +{ + char opt; + char *name = NULL; + int fd; + + while ((opt = getopt(argc, argv, "n:")) != -1) { + switch (opt) { + case 'n': + name = optarg; + break; + } + } + + if (!name) + usage(argv[0]); + + fd = lxc_monitor_open(name); + if (fd < 0) { + fprintf(stderr, "failed to open monitor\n"); + return -1; + } + + for (;;) { + lxc_state_t state; + lxc_monitor_read(fd, &state); + printf("received changing state '%s'\n", lxc_state2str(state)); + } +} diff --git a/test/lxc_monitor.c b/test/lxc_monitor.c index cd297af53..41e35b832 100644 --- a/test/lxc_monitor.c +++ b/test/lxc_monitor.c @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) } printf("container has changed the state to %d - %s\n", - state, state2str(state)); + state, lxc_state2str(state)); } return 0; diff --git a/test/lxc_state.c b/test/lxc_state.c index 2b4409130..a412bc9c1 100644 --- a/test/lxc_state.c +++ b/test/lxc_state.c @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) } printf("container has the state to %d - %s\n", - state, state2str(state)); + state, lxc_state2str(state)); return 0;