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
%files
%defattr(-,root,root)
%{_sysconfdir}/%{name}/*
+%{_libdir}/*.so*
%{_bindir}/*
%files devel
%{_includedir}/%{name}/*
%{_libdir}/*.a
+%post devel
+ln -sf %{_includedir}/%{name} %{_includedir}/liblxc
+
+
%changelog
* Sun Aug 3 2008 Daniel Lezcano <dlezcano@fr.ibm.com>
- Initial RPM release.
-lib_LIBRARIES = liblxc.a
+lib_LTLIBRARIES = liblxc.la
pkginclude_HEADERS = \
lxc.h \
lxc_cgroup.h \
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 \
nl.c nl.h \
rtnl.c rtnl.h \
genl.c genl.h
+
+liblxc_la_LDFLAGS = -release @PACKAGE_VERSION@
\ No newline at end of file
goto err;
}
- if (mkstate(name)) {
+ if (lxc_mkstate(name)) {
lxc_log_error("failed to create the state file for %s", name);
goto err;
}
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))
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);
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;
}
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
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;
}
}
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");
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);
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:
goto out;
}
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
if (flock(fd, LOCK_EX|LOCK_NB)) {
ret = errno == EWOULDBLOCK ? 0 : -errno;
close(fd);
#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 <lxc_state.h>
-#include <lxc_list.h>
-#include <lxc_conf.h>
-#include <lxc_log.h>
-#include <lxc_lock.h>
-#include <lxc_cgroup.h>
-#include <lxc_namespace.h>
-#include <lxc_utils.h>
+#include <liblxc/lxc_state.h>
+#include <liblxc/lxc_list.h>
+#include <liblxc/lxc_conf.h>
+#include <liblxc/lxc_log.h>
+#include <liblxc/lxc_lock.h>
+#include <liblxc/lxc_cgroup.h>
+#include <liblxc/lxc_namespace.h>
+#include <liblxc/lxc_utils.h>
#define LXCPATH "/var/lxc"
#define MAXPIDLEN 20
* 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
*/
extern int lxc_cgroup_get_cpu_usage(const char *name, long long *usage);
+#ifdef __cplusplus
+}
+#endif
+
#endif
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;
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];
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)
#include <sys/file.h>
#include <lxc.h>
+#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]);
{
int fd, err;
char file[MAXPATHLEN];
- const char *str = state2str(state);
+ const char *str = lxc_state2str(state);
if (!str)
return -1;
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
return -err;
}
-int mkstate(const char *name)
+int lxc_mkstate(const char *name)
{
int fd;
char file[MAXPATHLEN];
return 0;
}
-int rmstate(const char *name)
+int lxc_rmstate(const char *name)
{
char file[MAXPATHLEN];
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
file[err] = '\0';
close(fd);
- return str2state(file);
+ return lxc_str2state(file);
}
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;
}
return -1;
}
- return str2state(status);
+ return lxc_str2state(status);
}
lxc_state_t lxc_state(const char *name)
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
#include <errno.h>
#include <unistd.h>
#include <string.h>
+#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/inotify.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <netinet/in.h>
#include <net/if.h>
-
#include <lxc.h>
+#ifndef UNIX_PATH_MAX
+#define UNIX_PATH_MAX 108
+#endif
+
int lxc_monitor(const char *name, int output_fd)
{
char path[MAXPATHLEN];
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);
+}
/* 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;
}
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;
}
}
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");
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);
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:
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
--- /dev/null
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/utsname.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+#include <lxc.h>
+
+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;
+}
--- /dev/null
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * 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);
+
+
+
#include <net/if.h>
#include <lxc.h>
-
-#include "config.h"
+#include "lxc_config.h"
void usage(char *cmd)
{
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;
}
}
printf("container has changed the state to %d - %s\n",
- state, state2str(state));
+ state, lxc_state2str(state));
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <libgen.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <lxc.h>
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;
}
}
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;
return 1;
}
- printf("'%s' is %s\n", name, state2str(state));
+ printf("'%s' is %s\n", name, lxc_state2str(state));
return 0;
}
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
#include <lxc.h>
-#include "../src/lxc/config.h"
+#include "../src/lxc/lxc_config.h"
static void usage(const char *cmd)
{
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;
}
--- /dev/null
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ *
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <lxc.h>
+
+void usage(char *cmd)
+{
+ fprintf(stderr, "%s <command>\n", basename(cmd));
+ fprintf(stderr, "\t -n <name> : 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));
+ }
+}
}
printf("container has changed the state to %d - %s\n",
- state, state2str(state));
+ state, lxc_state2str(state));
}
return 0;
}
printf("container has the state to %d - %s\n",
- state, state2str(state));
+ state, lxc_state2str(state));
return 0;