Quoting Stéphane Graber (stgra...@ubuntu.com):
> On 05/15/2013 10:23 AM, Serge Hallyn wrote:
> > Add a clone hook called from api_clone.  Pass arguments to it from
> > lxc_clone.c.
> > 
> > The clone update hook is called while the container's bdev is mounted.
> > Information about the container is passed in through environment
> > variables LXC_ROOTFS_PATH, LXC_NAME, The LXC_ROOTFS_MOUNT, and
> > LXC_CONFIG_FILE.
> > 
> > LXC_ROOTFS_MOUNT=/usr/lib/x86_64-linux-gnu/lxc
> > LXC_CONFIG_FILE=/var/lib/lxc/demo3/config
> > LXC_ROOTFS_PATH=/var/lib/lxc/demo3/rootfs
> > LXC_NAME=demo3
> > 
> > So from the hook, updates to the container should be made under
> > $LXC_ROOTFS_MOUNT/ .
> > 
> > The hook also receives command line arguments as follows:
> > First argument is container name, second is always 'lxc', third
> > is the hook name (always clone), then come the arguments which
> > were passed to lxc-clone.  I.e. when I did:
> > 
> >     sudo lxc-clone demo2 demo3 -- hey there dude
> > 
> > the arguments passed in were "demo3 lxc clone hey there dude"
> > 
> > I personally would like to drop the first two arguments.  The
> > name is available as $LXC_NAME, and the section argument ('lxc')
> > is meaningless.  However, doing so risks invalidating existing
> > hooks.
> > 
> > Soon analogous create and destroy hooks will be added as well.
> 
> I think I'd have preferred storing the command arguments in
> LXC_CLONE_ARGS instead of directly in argv. Doing so would allow us to
> remove/add other arguments without breaking all existing hooks.
> 
> The user could then do "set -- $LXC_CLONE_ARGS" and just use $1... as usual.
> 
> But I'm not horribly opposed to the proposed implementation and the rest
> looks good.

Actually,

yeah that would let menot add the argv[] to run_lxc_hooks, and make the
patch quite a bit shorter.

I'll redo it like that.

Please don't apply :)

> Acked-by: Stéphane Graber <stgra...@ubuntu.com>
> 
> > Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
> > ---
> >  src/lxc/conf.c         | 63 
> > +++++++++++++++++++++++++++++++++++++++++++++-----
> >  src/lxc/conf.h         |  4 ++--
> >  src/lxc/confile.c      |  3 +++
> >  src/lxc/lxc_clone.c    | 16 ++++++-------
> >  src/lxc/lxccontainer.c | 55 ++++++++++++++++++++++++++++++-------------
> >  src/lxc/lxccontainer.h |  2 +-
> >  src/lxc/start.c        |  6 ++---
> >  7 files changed, 113 insertions(+), 36 deletions(-)
> > 
> > diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> > index 746a2db..61e45b1 100644
> > --- a/src/lxc/conf.c
> > +++ b/src/lxc/conf.c
> > @@ -173,7 +173,7 @@ return -1;
> >  #endif
> >  
> >  char *lxchook_names[NUM_LXC_HOOKS] = {
> > -   "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop" };
> > +   "pre-start", "pre-mount", "mount", "autodev", "start", "post-stop", 
> > "clone" };
> >  
> >  typedef int (*instanciate_cb)(struct lxc_handler *, struct lxc_netdev *);
> >  
> > @@ -336,6 +336,55 @@ static int run_buffer(char *buffer)
> >     return 0;
> >  }
> >  
> > +static int run_script_argv(const char *name, const char *section,
> > +                 const char *script, const char *hook, char **argsin)
> > +{
> > +   int ret, i;
> > +   char *buffer;
> > +   size_t size = 0;
> > +
> > +   INFO("Executing script '%s' for container '%s', config section '%s'",
> > +        script, name, section);
> > +
> > +   for (i=0; argsin && argsin[i]; i++)
> > +           size += strlen(argsin[i]) + 1;
> > +
> > +   size += strlen(hook) + 1;
> > +
> > +   size += strlen(script);
> > +   size += strlen(name);
> > +   size += strlen(section);
> > +   size += 3;
> > +
> > +   if (size > INT_MAX)
> > +           return -1;
> > +
> > +   buffer = alloca(size);
> > +   if (!buffer) {
> > +           ERROR("failed to allocate memory");
> > +           return -1;
> > +   }
> > +
> > +   ret = snprintf(buffer, size, "%s %s %s %s", script, name, section, 
> > hook);
> > +   if (ret < 0 || ret >= size) {
> > +           ERROR("Script name too long");
> > +           return -1;
> > +   }
> > +
> > +   for (i=0; argsin && argsin[i]; i++) {
> > +           int len = size-ret;
> > +           int rc;
> > +           rc = snprintf(buffer + ret, len, " %s", argsin[i]);
> > +           if (rc < 0 || rc >= len) {
> > +                   ERROR("Script args too long");
> > +                   return -1;
> > +           }
> > +           ret += rc;
> > +   }
> > +
> > +   return run_buffer(buffer);
> > +}
> > +
> >  static int run_script(const char *name, const char *section,
> >                   const char *script, ...)
> >  {
> > @@ -2752,7 +2801,7 @@ int lxc_setup(const char *name, struct lxc_conf 
> > *lxc_conf)
> >             return -1;
> >     }
> >  
> > -   if (run_lxc_hooks(name, "pre-mount", lxc_conf)) {
> > +   if (run_lxc_hooks(name, "pre-mount", lxc_conf, NULL)) {
> >             ERROR("failed to run pre-mount hooks for container '%s'.", 
> > name);
> >             return -1;
> >     }
> > @@ -2779,13 +2828,13 @@ int lxc_setup(const char *name, struct lxc_conf 
> > *lxc_conf)
> >             return -1;
> >     }
> >  
> > -   if (run_lxc_hooks(name, "mount", lxc_conf)) {
> > +   if (run_lxc_hooks(name, "mount", lxc_conf, NULL)) {
> >             ERROR("failed to run mount hooks for container '%s'.", name);
> >             return -1;
> >     }
> >  
> >     if (lxc_conf->autodev) {
> > -           if (run_lxc_hooks(name, "autodev", lxc_conf)) {
> > +           if (run_lxc_hooks(name, "autodev", lxc_conf, NULL)) {
> >                     ERROR("failed to run autodev hooks for container 
> > '%s'.", name);
> >                     return -1;
> >             }
> > @@ -2852,7 +2901,7 @@ 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 run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, 
> > char *argv[])
> >  {
> >     int which = -1;
> >     struct lxc_list *it;
> > @@ -2869,12 +2918,14 @@ int run_lxc_hooks(const char *name, char *hook, 
> > struct lxc_conf *conf)
> >             which = LXCHOOK_START;
> >     else if (strcmp(hook, "post-stop") == 0)
> >             which = LXCHOOK_POSTSTOP;
> > +   else if (strcmp(hook, "clone") == 0)
> > +           which = LXCHOOK_CLONE;
> >     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);
> > +           ret = run_script_argv(name, "lxc", hookname, hook, argv);
> >             if (ret)
> >                     return ret;
> >     }
> > diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> > index 465b1ec..5139aa3 100644
> > --- a/src/lxc/conf.h
> > +++ b/src/lxc/conf.h
> > @@ -237,7 +237,7 @@ struct lxc_rootfs {
> >   */
> >  enum lxchooks {
> >     LXCHOOK_PRESTART, LXCHOOK_PREMOUNT, LXCHOOK_MOUNT, LXCHOOK_AUTODEV,
> > -   LXCHOOK_START, LXCHOOK_POSTSTOP, NUM_LXC_HOOKS};
> > +   LXCHOOK_START, LXCHOOK_POSTSTOP, LXCHOOK_CLONE, NUM_LXC_HOOKS};
> >  extern char *lxchook_names[NUM_LXC_HOOKS];
> >  
> >  struct saved_nic {
> > @@ -284,7 +284,7 @@ struct lxc_conf {
> >     char *rcfile;   // Copy of the top level rcfile we read
> >  };
> >  
> > -int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf);
> > +int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf, 
> > char *argv[]);
> >  
> >  extern int setup_cgroup(const char *cgpath, struct lxc_list *cgroups);
> >  extern int detect_shared_rootfs(void);
> > diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> > index aec8177..fb851c9 100644
> > --- a/src/lxc/confile.c
> > +++ b/src/lxc/confile.c
> > @@ -117,6 +117,7 @@ static struct lxc_config_t config[] = {
> >     { "lxc.hook.autodev",         config_hook                 },
> >     { "lxc.hook.start",           config_hook                 },
> >     { "lxc.hook.post-stop",       config_hook                 },
> > +   { "lxc.hook.clone",           config_hook                 },
> >     { "lxc.network.type",         config_network_type         },
> >     { "lxc.network.flags",        config_network_flags        },
> >     { "lxc.network.link",         config_network_link         },
> > @@ -894,6 +895,8 @@ static int config_hook(const char *key, const char 
> > *value,
> >             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);
> > +   else if (strcmp(key, "lxc.hook.clone") == 0)
> > +           return add_hook(lxc_conf, LXCHOOK_CLONE, copy);
> >     SYSERROR("Unknown key: %s", key);
> >     free(copy);
> >     return -1;
> > diff --git a/src/lxc/lxc_clone.c b/src/lxc/lxc_clone.c
> > index b9c7a6e..2b0ee43 100644
> > --- a/src/lxc/lxc_clone.c
> > +++ b/src/lxc/lxc_clone.c
> > @@ -16,7 +16,7 @@
> >  
> >  lxc_log_define(lxc_clone, lxc);
> >  
> > -void usage(char *me)
> > +void usage(const char *me)
> >  {
> >     printf("Usage: %s [-s] [-B backingstore] [-L size] [-K] [-M] [-H]\n", 
> > me);
> >     printf("          [-p lxcpath] [-P newlxcpath] orig new\n");
> > @@ -60,6 +60,7 @@ int main(int argc, char *argv[])
> >     long newsize = 0;
> >     char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL;
> >     char *orig = NULL, *new = NULL, *vgname = NULL;
> > +   char **args = NULL;
> >     char c;
> >  
> >     if (argc < 3)
> > @@ -86,14 +87,13 @@ int main(int argc, char *argv[])
> >             default: break;
> >             }
> >     }
> > -   if (optind == argc-2 && !orig)
> > +    if (optind < argc && !orig)
> >             orig = argv[optind++];
> > -   if (optind == argc-1 && !new)
> > +    if (optind < argc && !new)
> >             new = argv[optind++];
> > -   if (optind < argc) {
> > -           printf("%d extraneous arguments\n", argc-optind);
> > -           usage(argv[0]);
> > -   }
> > +   if (optind < argc)
> > +           /* arguments for the clone hook */
> > +           args = &argv[optind];
> >     if (!new || !orig) {
> >             printf("Error: you must provide orig and new names\n");
> >             usage(argv[0]);
> > @@ -124,7 +124,7 @@ int main(int argc, char *argv[])
> >             lxc_container_put(c1);
> >             exit(1);
> >     }
> > -   c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize);
> > +   c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize, args);
> >     if (c2 == NULL) {
> >             lxc_container_put(c1);
> >             fprintf(stderr, "clone failed\n");
> > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > index bac94c2..23db6f2 100644
> > --- a/src/lxc/lxccontainer.c
> > +++ b/src/lxc/lxccontainer.c
> > @@ -1364,16 +1364,14 @@ static int copy_storage(struct lxc_container *c0, 
> > struct lxc_container *c,
> >     return 0;
> >  }
> >  
> > -static int clone_update_rootfs(struct lxc_container *c, int flags)
> > +static int clone_update_rootfs(struct lxc_container *c, int flags, char 
> > **hookargs)
> >  {
> >     int ret = -1;
> >     char path[MAXPATHLEN];
> >     struct bdev *bdev;
> >     FILE *fout;
> >     pid_t pid;
> > -
> > -   if (flags & LXC_CLONE_KEEPNAME)
> > -           return 0;
> > +   struct lxc_conf *conf = c->lxc_conf;
> >  
> >     /* update hostname in rootfs */
> >     /* we're going to mount, so run in a clean namespace to simplify 
> > cleanup */
> > @@ -1393,17 +1391,41 @@ static int clone_update_rootfs(struct lxc_container 
> > *c, int flags)
> >             exit(1);
> >     if (bdev->ops->mount(bdev) < 0)
> >             exit(1);
> > -   ret = snprintf(path, MAXPATHLEN, "%s/etc/hostname", bdev->dest);
> > -   if (ret < 0 || ret >= MAXPATHLEN)
> > -           exit(1);
> > -   if (!(fout = fopen(path, "w"))) {
> > -           SYSERROR("unable to open %s: ignoring\n", path);
> > -           exit(0);
> > +
> > +   if (!lxc_list_empty(&conf->hooks[LXCHOOK_CLONE])) {
> > +           /* Start of environment variable setup for hooks */
> > +           if (setenv("LXC_NAME", c->name, 1)) {
> > +                   SYSERROR("failed to set environment variable for 
> > container name");
> > +           }
> > +           if (setenv("LXC_CONFIG_FILE", conf->rcfile, 1)) {
> > +                   SYSERROR("failed to set environment variable for config 
> > path");
> > +           }
> > +           if (setenv("LXC_ROOTFS_MOUNT", conf->rootfs.mount, 1)) {
> > +                   SYSERROR("failed to set environment variable for rootfs 
> > mount");
> > +           }
> > +           if (setenv("LXC_ROOTFS_PATH", conf->rootfs.path, 1)) {
> > +                   SYSERROR("failed to set environment variable for rootfs 
> > mount");
> > +           }
> > +
> > +           if (run_lxc_hooks(c->name, "clone", conf, hookargs)) {
> > +                   ERROR("Error executing clone hook for %s", c->name);
> > +                   exit(1);
> > +           }
> > +   }
> > +
> > +   if (!(flags & LXC_CLONE_KEEPNAME)) {
> > +           ret = snprintf(path, MAXPATHLEN, "%s/etc/hostname", bdev->dest);
> > +           if (ret < 0 || ret >= MAXPATHLEN)
> > +                   exit(1);
> > +           if (!(fout = fopen(path, "w"))) {
> > +                   SYSERROR("unable to open %s: ignoring\n", path);
> > +                   exit(0);
> > +           }
> > +           if (fprintf(fout, "%s", c->name) < 0)
> > +                   exit(1);
> > +           if (fclose(fout) < 0)
> > +                   exit(1);
> >     }
> > -   if (fprintf(fout, "%s", c->name) < 0)
> > -           exit(1);
> > -   if (fclose(fout) < 0)
> > -           exit(1);
> >     exit(0);
> >  }
> >  
> > @@ -1436,7 +1458,8 @@ static int create_file_dirname(char *path)
> >  
> >  struct lxc_container *lxcapi_clone(struct lxc_container *c, const char 
> > *newname,
> >             const char *lxcpath, int flags,
> > -           const char *bdevtype, const char *bdevdata, unsigned long 
> > newsize)
> > +           const char *bdevtype, const char *bdevdata, unsigned long 
> > newsize,
> > +           char **hookargs)
> >  {
> >     struct lxc_container *c2 = NULL;
> >     char newpath[MAXPATHLEN];
> > @@ -1525,7 +1548,7 @@ struct lxc_container *lxcapi_clone(struct 
> > lxc_container *c, const char *newname,
> >     if (!c2->save_config(c2, NULL))
> >             goto out;
> >  
> > -   if (clone_update_rootfs(c2, flags) < 0)
> > +   if (clone_update_rootfs(c2, flags, hookargs) < 0)
> >             goto out;
> >  
> >     // TODO: update c's lxc.snapshot = count
> > diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> > index b6bd97c..67fbed4 100644
> > --- a/src/lxc/lxccontainer.h
> > +++ b/src/lxc/lxccontainer.h
> > @@ -105,7 +105,7 @@ struct lxc_container {
> >      */
> >     struct lxc_container *(*clone)(struct lxc_container *c, const char 
> > *newname,
> >             const char *lxcpath, int flags, const char *bdevtype,
> > -           const char *bdevdata, unsigned long newsize);
> > +           const char *bdevdata, unsigned long newsize, char **hookargs);
> >  
> >  #if 0
> >     bool (*commit_cgroups)(struct lxc_container *c);
> > diff --git a/src/lxc/start.c b/src/lxc/start.c
> > index fd96d4f..995460e 100644
> > --- a/src/lxc/start.c
> > +++ b/src/lxc/start.c
> > @@ -461,7 +461,7 @@ struct lxc_handler *lxc_init(const char *name, struct 
> > lxc_conf *conf, const char
> >     }
> >     /* End of environment variable setup for hooks */
> >  
> > -   if (run_lxc_hooks(name, "pre-start", conf)) {
> > +   if (run_lxc_hooks(name, "pre-start", conf, NULL)) {
> >             ERROR("failed to run pre-start hooks for container '%s'.", 
> > name);
> >             goto out_aborting;
> >     }
> > @@ -513,7 +513,7 @@ static void lxc_fini(const char *name, struct 
> > lxc_handler *handler)
> >     lxc_set_state(name, handler, STOPPING);
> >     lxc_set_state(name, handler, STOPPED);
> >  
> > -   if (run_lxc_hooks(name, "post-stop", handler->conf))
> > +   if (run_lxc_hooks(name, "post-stop", handler->conf, NULL))
> >             ERROR("failed to run post-stop hooks for container '%s'.", 
> > name);
> >  
> >     /* reset mask set by setup_signal_fd */
> > @@ -676,7 +676,7 @@ static int do_start(void *data)
> >     if (lxc_seccomp_load(handler->conf) != 0)
> >             goto out_warn_father;
> >  
> > -   if (run_lxc_hooks(handler->name, "start", handler->conf)) {
> > +   if (run_lxc_hooks(handler->name, "start", handler->conf, NULL)) {
> >             ERROR("failed to run start hooks for container '%s'.", 
> > handler->name);
> >             goto out_warn_father;
> >     }
> > 
> 
> 
> -- 
> Stéphane Graber
> Ubuntu developer
> http://www.ubuntu.com
> 



------------------------------------------------------------------------------
AlienVault Unified Security Management (USM) platform delivers complete
security visibility with the essential security capabilities. Easily and
efficiently configure, manage, and operate all of your security controls
from a single console and one unified framework. Download a free trial.
http://p.sf.net/sfu/alienvault_d2d
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to