* execute `$datadir/lxc/scripts/mconf $datadir/lxc/scripts/create.conf'
        * read .config to fill lxc_arguments

Signed-off-by: Sheng Yong <[email protected]>
---
 src/lxc/Makefile.am  |   1 +
 src/lxc/lxc_create.c | 416 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 417 insertions(+)

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index ab8a46e..99f7f38 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -116,6 +116,7 @@ AM_CFLAGS=-I$(top_srcdir)/src \
        -DLXCINITDIR=\"$(LXCINITDIR)\" \
        -DLIBEXECDIR=\"$(LIBEXECDIR)\" \
        -DLXCTEMPLATEDIR=\"$(LXCTEMPLATEDIR)\" \
+       -DLXCSCRIPTDIR=\"$(LXCSCRIPTDIR)\" \
        -DLOGPATH=\"$(LOGPATH)\" \
        -DLXC_DEFAULT_CONFIG=\"$(LXC_DEFAULT_CONFIG)\" \
        -DLXC_USERNIC_DB=\"$(LXC_USERNIC_DB)\" \
diff --git a/src/lxc/lxc_create.c b/src/lxc/lxc_create.c
index 6b595f9..8a6a49d 100644
--- a/src/lxc/lxc_create.c
+++ b/src/lxc/lxc_create.c
@@ -32,9 +32,65 @@
 #include "bdev.h"
 #include "arguments.h"
 #include "utils.h"
+#include "parse.h"
+#include "confile.h"
 
 lxc_log_define(lxc_create_ui, lxc);
 
+static int create_config_file(const char *, const char *, struct lxc_conf *);
+static int create_config_template(const char *, const char *, struct lxc_conf 
*);
+static int create_config_backdev(const char *, const char *, struct lxc_conf 
*);
+static int create_config_backdev_lvm(const char *, const char *, struct 
lxc_conf *);
+static int create_config_lxc_path(const char *, const char *, struct lxc_conf 
*);
+static int create_config_log_file(const char *, const char *, struct lxc_conf 
*);
+static int create_config_log_prio(const char *, const char *, struct lxc_conf 
*);
+static int create_config_quiet(const char *, const char *, struct lxc_conf *);
+
+static struct lxc_config_t create_config[] = {
+
+       { "CONFIG_FILE",              create_config_file          },
+       { "TEMP_none",                create_config_template      },
+       { "TEMP_alpine",              create_config_template      },
+       { "TEMP_altlinux",            create_config_template      },
+       { "TEMP_archlinux",           create_config_template      },
+       { "TEMP_busybox",             create_config_template      },
+       { "TEMP_centos",              create_config_template      },
+       { "TEMP_cirros",              create_config_template      },
+       { "TEMP_debian",              create_config_template      },
+       { "TEMP_download",            create_config_template      },
+       { "TEMP_fedora",              create_config_template      },
+       { "TEMP_gentoo",              create_config_template      },
+       { "TEMP_openmandriva",        create_config_template      },
+       { "TEMP_opensuse",            create_config_template      },
+       { "TEMP_oracle",              create_config_template      },
+       { "TEMP_plamo",               create_config_template      },
+       { "TEMP_sshd",                create_config_template      },
+       { "TEMP_ubuntu",              create_config_template      },
+       { "TEMP_ubuntu_cloud",        create_config_template      },
+       { "BS_NONE",                  create_config_backdev       },
+       { "BS_dir",                   create_config_backdev       },
+       { "BS_lvm",                   create_config_backdev       },
+       { "BS_loop",                  create_config_backdev       },
+       { "BS_btrfs",                 create_config_backdev       },
+       { "BS_best",                  create_config_backdev       },
+       { "BS_LVM_LVNAME",            create_config_backdev_lvm   },
+       { "BS_LVM_VGNAME",            create_config_backdev_lvm   },
+       { "BS_LVM_THINPOOL",          create_config_backdev_lvm   },
+       { "BS_LVM_FSTYPE",            create_config_backdev_lvm   },
+       { "BS_LVM_FSSIZE",            create_config_backdev_lvm   },
+       { "LXC_PATH",                 create_config_lxc_path      },
+       { "LOG_FILE",                 create_config_log_file      },
+       { "LOG_PRIO_FATAL",           create_config_log_prio      },
+       { "LOG_PRIO_CRIT",            create_config_log_prio      },
+       { "LOG_PRIO_WARN",            create_config_log_prio      },
+       { "LOG_PRIO_ERROR",           create_config_log_prio      },
+       { "LOG_PRIO_NOTICE",          create_config_log_prio      },
+       { "LOG_PRIO_INFO",            create_config_log_prio      },
+       { "LOG_PRIO_DEBUG",           create_config_log_prio      },
+       { "QUIET",                    create_config_quiet         }
+};
+static const size_t createconfig_size = sizeof(create_config)/sizeof(struct 
lxc_config_t);
+
 static uint64_t get_fssize(char *s)
 {
        uint64_t ret;
@@ -68,6 +124,352 @@ static uint64_t get_fssize(char *s)
        return ret;
 }
 
+static char* remove_left_right_quotation(char *buffer)
+{
+       if (*buffer == '"')
+               buffer++;
+       if (buffer[strlen(buffer)-1] == '"')
+               buffer[strlen(buffer)-1] = '\0';
+       return buffer;
+}
+
+static int create_config_file(const char *key, const char *value,
+                             struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       int len = strlen(value);
+
+       if (len == 0) // must be empty value
+               return 0;
+
+       args->configfile = malloc(len + 1);
+       if (!args->configfile) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+       strncpy(args->configfile, value, len);
+       args->configfile[len] = '\0';
+
+       return 0;
+}
+
+static int create_config_template(const char *key, const char *value,
+                                 struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+
+       char *template = (char *) (key + 5); //skip the first 5 char 'TEMP_'
+       int len;
+
+       if (strncmp(value, "y", 1)) {
+               SYSERROR("unknown configure value '%s'", value);
+               return -1;
+       }
+
+       len = strlen(template);
+       args->template = malloc(len + 1);
+       if (!args->template) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+       strncpy(args->template, template, len);
+       args->template[len] = '\0';
+
+       return 0;
+}
+
+static int create_config_backdev(const char *key, const char *value,
+                                struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       char *bs = (char *) (key + 3); //skip the first 3 char 'BS_'
+       int len;
+
+       if (strncmp("y", value, 1)) {
+               SYSERROR("unknown configure value '%s'", value);
+               return -1;
+       }
+
+       if (!strncmp(bs, "NONE", 5)) {
+               return 0;
+       }
+
+       len = strlen(bs);
+       args->bdevtype = malloc(len + 1);
+       if (!args->bdevtype) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+       strncpy(args->bdevtype, bs, len);
+       args->bdevtype[len] = '\0';
+
+       return 0;
+}
+
+static int create_config_backdev_lvm(const char *key, const char *value,
+                                    struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       char lvms[5][9] = {"LVNAME", "VGNAME", "THINPOOL", "FSTYPE", "FSSIZE"};
+       char *lvm = (char *) (key + 7); //skip the first 7 char 'BS_LVM_'
+       char *tmp;
+       int len, i;
+
+       for (i = 0; i < 5; i++) {
+               if (!strncmp(lvm, lvms[i], strlen(lvms[i])))
+                       break;
+       }
+       if (i == 5) {
+               SYSERROR("unknown option '%s'", lvm);
+               return 0;
+       }
+
+       len = strlen(value);
+       if (len == 0) // must be empty value
+               return 0;
+
+       tmp = malloc(len + 1);
+       if (!tmp) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+       strncpy(tmp, value, len);
+       tmp[len] = '\0';
+
+       switch(i) {
+       case 0: args->lvname = tmp; break;
+       case 1: args->vgname = tmp; break;
+       case 2: args->thinpool = tmp; break;
+       case 3: args->fstype = tmp; break;
+       case 4: args->fssize = get_fssize(tmp); break;
+       }
+
+       return 0;
+}
+
+static int create_config_lxc_path(const char *key, const char *value,
+                                 struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       char *path = strdup(value);
+
+       if (!path) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+
+       remove_trailing_slashes(path);
+
+       args->lxcpath = realloc(args->lxcpath, (args->lxcpath_cnt + 1) *
+                                sizeof(args->lxcpath[0]));
+       if (args->lxcpath == NULL) {
+               SYSERROR("failed to allocate memory");
+               return -ENOMEM;
+       }
+       args->lxcpath[args->lxcpath_cnt++] = path;
+
+       return 0;
+}
+
+static int create_config_log_file(const char *key, const char *value,
+                                 struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       int len = strlen(value);
+
+       if (len == 0) // must be empty value
+               return 0;
+
+       args->log_file = malloc(len + 1);
+       if (!args->log_file) {
+               SYSERROR("failed to allocate memroy");
+               return -1;
+       }
+
+       strncpy(args->log_file, value, len);
+       args->log_file[len] = '\0';
+
+       return 0;
+}
+
+static int create_config_log_prio(const char *key, const char *value,
+                                 struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+       char *prio = (char *) (key + 9);        // skip the first 9 char 
'LOG_PRIO_'
+       int len;
+
+       if (strncmp(value, "y", 1)) {
+               SYSERROR("unknown configure value '%s'", value);
+               return -1;
+       }
+
+       if (!strncmp(prio, "ERROR", 6))
+               return 0;
+
+       len = strlen(prio);
+       args->log_priority = malloc(len + 1);
+       if (!args->log_priority) {
+               SYSERROR("failed to allocate memory");
+               return -1;
+       }
+
+       strncpy(args->log_priority, prio, len);
+       args->log_priority[len] = '\0';
+
+       return 0;
+}
+
+static int create_config_quiet(const char *key, const char *value,
+                              struct lxc_conf *lxc_conf)
+{
+       struct lxc_arguments *args = (struct lxc_arguments *) lxc_conf;
+
+       if (strncmp("y", value, 1)) {
+               SYSERROR("unknown configure value '%s'", value);
+               return -1;
+       }
+
+       args->quiet = 1;
+
+       return 0;
+}
+
+static bool menuconfig(struct lxc_arguments* args)
+{
+       pid_t pid;
+
+       pid = fork();
+       if (pid < 0) {
+               SYSERROR("failed to fork task for container creation 
menuconfig");
+               return false;
+       }
+
+       if (pid == 0) {
+               char **argv;
+               int len;
+
+               len = strlen(LXCSCRIPTDIR) + strlen("/create.conf") + 1;
+               argv = malloc(3 * sizeof(*argv));
+               if (!argv) {
+                       return false;
+               }
+
+               len = strlen(LXCSCRIPTDIR) + strlen("/mconf") + 1;
+               argv[0] = malloc(len);
+               if (!argv[0]) {
+                       free(argv);
+                       return false;
+               }
+               sprintf(argv[0], "%s/mconf", LXCSCRIPTDIR);
+
+               argv[1] = malloc(len);
+               if (!argv[1]) {
+                       free(argv[0]);
+                       free(argv);
+                       return false;
+               }
+               sprintf(argv[1], "%s/create.conf", LXCSCRIPTDIR);
+
+               argv[2] = NULL;
+
+               execv(argv[0], argv);
+               SYSERROR("failed to execute menuconfig %s %s", argv[0], 
argv[1]);
+               exit(1);
+       }
+
+       if (wait_for_pid(pid) != 0) {
+               ERROR("container container creation for %s failed\n", 
args->name);
+               return false;
+       }
+
+       return true;
+}
+
+static struct lxc_config_t *lxc_getcreateconfig(const char *key)
+{
+       int i;
+
+       for (i = 0; i < createconfig_size; i++)
+               if (!strncmp(create_config[i].name, key,
+                            strlen(create_config[i].name)))
+                       return &create_config[i];
+       return NULL;
+}
+
+static int parse_config(char *buffer, void *data)
+{
+       struct lxc_config_t *create_config;
+       char *line, *linep, *key, *value;
+       int ret = 0;
+
+       if (lxc_is_line_empty(buffer))
+               return 0;
+
+       linep = line = strdup(buffer);
+       if (!line) {
+               SYSERROR("failed to allocate memory for '%s'", buffer);
+               return -1;
+       }
+
+       line += lxc_char_left_gc(line, strlen(line));
+
+       /* ignore this line if it is commented or not started with CONFIG_ */
+       if ((*line == '#') || strncmp(line, "CONFIG_", 7))
+               goto out;
+
+       line += 7;
+       key = line;
+       value = NULL;
+       while (*line != '\n') {
+               if ((*line >= 'A' && *line <= 'Z') ||
+                   (*line >= 'a' && *line <= 'z') ||
+                   (*line >= '0' && *line <= '9') ||
+                   (*line == '_' )) {
+                       line++;
+                       continue;
+               } else if (*line == ' ' || *line == '=') {
+                       *line = '\0';
+                       value = line + 1;
+                       break;
+               }
+       }
+       if (!value) {
+               ERROR("invalid creation configuration line: %s", linep);
+               goto out;
+       }
+
+       value += lxc_char_left_gc(value, strlen(value));
+       value[lxc_char_right_gc(value, strlen(value))] = '\0';
+       value = remove_left_right_quotation(value);
+
+       create_config = lxc_getcreateconfig(key);
+       if (!create_config) {
+               ERROR("unknown key %s", key);
+               goto out;
+       }
+
+       ret = create_config->cb(key, value, data);
+
+out:
+       free(linep);
+       return ret;
+}
+
+static bool read_conf_set_args(struct lxc_arguments* args)
+{
+       char *def_conf = ".config";
+
+       if (access(def_conf, R_OK) < 0) {
+               return false;
+       }
+
+       if (!lxc_file_for_each_line(def_conf, parse_config, args))
+               return true;
+
+       return false;
+}
+
 static int my_parser(struct lxc_arguments* args, int c, char* arg)
 {
        switch (c) {
@@ -81,6 +483,18 @@ static int my_parser(struct lxc_arguments* args, int c, 
char* arg)
        case '4': args->fssize = get_fssize(arg); break;
        case '5': args->zfsroot = arg; break;
        case '6': args->dir = arg; break;
+       case 'm':
+               /* create menuconfig */
+               if (!menuconfig(args)) {
+                       fprintf(stderr, "Create menuconfig failed!\n");
+                       return 1;
+               }
+               /* read config file, and set args */
+               if (!read_conf_set_args(args)) {
+                       fprintf(stderr, "Failed to read creation config 
file!\n");
+                       return 1;
+               }
+               break;
        }
        return 0;
 }
@@ -96,6 +510,7 @@ static const struct option my_longopts[] = {
        {"fssize", required_argument, 0, '4'},
        {"zfsroot", required_argument, 0, '5'},
        {"dir", required_argument, 0, '6'},
+       {"menuconfig", no_argument, 0, 'm'},
        LXC_COMMON_OPTIONS
 };
 
@@ -138,6 +553,7 @@ lxc-create creates a container\n\
 \n\
 Options :\n\
   -n, --name=NAME    NAME for name of the container\n\
+  -m, --menuconfig   Interactive configuration\n\
   -f, --config=file  Initial configuration file\n\
   -t, --template=t   Template to use to setup container\n\
   -B, --bdev=BDEV    Backing store type to use\n\
-- 
1.9.1

_______________________________________________
lxc-devel mailing list
[email protected]
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to