[Lxc-users] [lxc-devel] [PATCH RFC] Introduce a first set of container hooks
Serge Hallyn
serge.hallyn at canonical.com
Thu Jun 21 15:32:01 UTC 2012
Hi,
any comments on this patch? If there are no major objections to the
fundamental patch (the lxc.conf entries and the basic hooks), I will go
ahead and get it into our ubuntu package to get it some more testing.
thanks,
-serge
Quoting Serge Hallyn (serge.hallyn at canonical.com):
> This patch introduces support for 4 hooks. We'd like to have 6 in
> all to mirror the openvz ones (thanks to Stéphane for this info):
>
> pre-start: in the host namespace before container mounting happens
> mount: after container mounting (as per config and /var/lib/lxc/container/fstab)
> but before pivot_root
> start: immediately before exec'ing init
> stop: in container namespace and in chroot before shutdown
> umount: after other unmounting has happened
> post-stop: outside of the container
>
> stop and umount are not implemented here because when the kernel kills
> the container init, it kills the namespace. We can probably work around
> this, i.e. by keeping the /proc/pid/ns/mnt open, and using that, though
> all container tasks including init would still be dead. Is that worth
> pursuing?
>
> start also presents a bit of an issue. openvz allows a script on the
> host to be specified, apparently. My patch requires the script or
> program to exist in the container. I'm fine with trying to do it the
> openvz way, but I wasn't sure what the best way to do that was. Openvz
> (I'm told) opens the script and passes its contents to a bash in the
> container. But that limits the hooks to being only scripts. By
> requiring the hook to be in the container, we can allow any sort of
> hook, and assume that any required libraries/dependencies exist
> there.
>
> Other than that with this patchset I can add
>
> lxc.hook.pre-start = /var/lib/lxc/p1/pre-start
> lxc.hook.mount = /var/lib/lxc/p1/mount
> lxc.hook.start = /start
> lxc.hook.post-stop = /var/lib/lxc/p1/post-stop
>
> to my /var/lib/lxc/p1/config, and the hooks get executed as expected.
> Comments on the patch, the hooks we want, and the questions raised above
> would be appreciated.
>
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
> ---
> src/lxc/conf.c | 29 +++++++++++++++++++++++++++++
> src/lxc/conf.h | 12 ++++++++++++
> src/lxc/confile.c | 40 ++++++++++++++++++++++++++++++++++++++++
> src/lxc/start.c | 6 ++++++
> 4 files changed, 87 insertions(+)
>
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index e8088bb..546d9fc 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -1572,6 +1572,7 @@ static int setup_private_host_hw_addr(char *veth1)
> struct lxc_conf *lxc_conf_init(void)
> {
> struct lxc_conf *new;
> + int i;
>
> new = malloc(sizeof(*new));
> if (!new) {
> @@ -1591,6 +1592,8 @@ struct lxc_conf *lxc_conf_init(void)
> lxc_list_init(&new->network);
> lxc_list_init(&new->mount_list);
> lxc_list_init(&new->caps);
> + for (i=0; i<NUM_LXC_HOOKS; i++)
> + lxc_list_init(&new->hooks[i]);
>
> return new;
> }
> @@ -2012,6 +2015,7 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
> return -1;
> }
>
> + HOOK(name, "mount", lxc_conf);
> if (setup_cgroup(name, &lxc_conf->cgroup)) {
> ERROR("failed to setup the cgroups for '%s'", name);
> return -1;
> @@ -2051,3 +2055,28 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
>
> return 0;
> }
> +
> +int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf)
> +{
> + int which = -1;
> + struct lxc_list *it;
> +
> + if (strcmp(hook, "pre-start") == 0)
> + which = LXCHOOK_PRESTART;
> + else if (strcmp(hook, "mount") == 0)
> + which = LXCHOOK_MOUNT;
> + else if (strcmp(hook, "start") == 0)
> + which = LXCHOOK_START;
> + else if (strcmp(hook, "post-stop") == 0)
> + which = LXCHOOK_POSTSTOP;
> + else
> + return -1;
> + lxc_list_for_each(it, &conf->hooks[which]) {
> + int ret;
> + char *hookname = it->elem;
> + ret = run_script(name, "lxc", hookname, hook, NULL);
> + if (ret)
> + return ret;
> + }
> + return 0;
> +}
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index 09f55cb..c91872b 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -199,6 +199,9 @@ struct lxc_rootfs {
> * @console : console data
> * @ttydir : directory (under /dev) in which to create console and ttys
> */
> +enum lxchooks {
> + LXCHOOK_PRESTART, LXCHOOK_MOUNT, LXCHOOK_START,
> + LXCHOOK_POSTSTOP, NUM_LXC_HOOKS};
> struct lxc_conf {
> char *fstab;
> int tty;
> @@ -216,8 +219,17 @@ struct lxc_conf {
> struct lxc_rootfs rootfs;
> char *ttydir;
> int close_all_fds;
> + struct lxc_list hooks[NUM_LXC_HOOKS];
> };
>
> +int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf);
> +/* we don't want to stick with the HOOK define, it's just to easily start */
> +#define HOOK(name, which, conf) \
> + do { \
> + int hookret = run_lxc_hooks(name, which, conf); \
> + if (hookret) return -1; \
> + } while (0);
> +
> /*
> * Initialize the lxc configuration structure
> */
> diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> index b305aef..75cf4d7 100644
> --- a/src/lxc/confile.c
> +++ b/src/lxc/confile.c
> @@ -55,6 +55,7 @@ static int config_rootfs(const char *, char *, struct lxc_conf *);
> static int config_rootfs_mount(const char *, char *, struct lxc_conf *);
> static int config_pivotdir(const char *, char *, struct lxc_conf *);
> static int config_utsname(const char *, char *, struct lxc_conf *);
> +static int config_hook(const char *key, char *value, struct lxc_conf *lxc_conf);
> static int config_network_type(const char *, char *, struct lxc_conf *);
> static int config_network_flags(const char *, char *, struct lxc_conf *);
> static int config_network_link(const char *, char *, struct lxc_conf *);
> @@ -91,6 +92,10 @@ static struct config config[] = {
> { "lxc.rootfs", config_rootfs },
> { "lxc.pivotdir", config_pivotdir },
> { "lxc.utsname", config_utsname },
> + { "lxc.hook.pre-start", config_hook },
> + { "lxc.hook.mount", config_hook },
> + { "lxc.hook.start", config_hook },
> + { "lxc.hook.post-stop", config_hook },
> { "lxc.network.type", config_network_type },
> { "lxc.network.flags", config_network_flags },
> { "lxc.network.link", config_network_link },
> @@ -584,6 +589,41 @@ static int config_network_script(const char *key, char *value,
> return -1;
> }
>
> +static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
> +{
> + struct lxc_list *hooklist;
> +
> + hooklist = malloc(sizeof(*hooklist));
> + if (!hooklist) {
> + free(hook);
> + return -1;
> + }
> + hooklist->elem = hook;
> + lxc_list_add_tail(&lxc_conf->hooks[which], hooklist);
> + return 0;
> +}
> +
> +static int config_hook(const char *key, char *value,
> + struct lxc_conf *lxc_conf)
> +{
> + char *copy = strdup(value);
> + if (!copy) {
> + SYSERROR("failed to dup string '%s'", value);
> + return -1;
> + }
> + if (strcmp(key, "lxc.hook.pre-start") == 0)
> + return add_hook(lxc_conf, LXCHOOK_PRESTART, copy);
> + else if (strcmp(key, "lxc.hook.mount") == 0)
> + return add_hook(lxc_conf, LXCHOOK_MOUNT, copy);
> + else if (strcmp(key, "lxc.hook.start") == 0)
> + return add_hook(lxc_conf, LXCHOOK_START, copy);
> + else if (strcmp(key, "lxc.hook.post-stop") == 0)
> + return add_hook(lxc_conf, LXCHOOK_POSTSTOP, copy);
> + SYSERROR("Unknown key: %s", key);
> + free(copy);
> + return -1;
> +}
> +
> static int config_personality(const char *key, char *value,
> struct lxc_conf *lxc_conf)
> {
> diff --git a/src/lxc/start.c b/src/lxc/start.c
> index 920ff77..eba444d 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -357,6 +357,8 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf)
> goto out_free_name;
> }
>
> + HOOK(name, "pre-start", conf);
> +
> if (lxc_create_tty(name, conf)) {
> ERROR("failed to create the ttys");
> goto out_aborting;
> @@ -401,6 +403,8 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
> lxc_set_state(name, handler, STOPPING);
> lxc_set_state(name, handler, STOPPED);
>
> + HOOK(name, "post-stop", handler->conf);
> +
> /* reset mask set by setup_signal_fd */
> if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL))
> WARN("failed to restore sigprocmask");
> @@ -519,6 +523,8 @@ static int do_start(void *data)
>
> close(handler->sigfd);
>
> + HOOK(handler->name, "start", handler->conf);
> +
> /* after this call, we are in error because this
> * ops should not return as it execs */
> if (handler->ops->start(handler, handler->data))
> --
> 1.7.9.5
>
>
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel
More information about the lxc-users
mailing list