]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/tools/lxc_create.c
Add template-options to help output
[mirror_lxc.git] / src / lxc / tools / lxc_create.c
CommitLineData
1897e3bc
SH
1/*
2 *
3 * Copyright © 2013 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2013 Canonical Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
d38dd64a
CB
20#ifndef _GNU_SOURCE
21#define _GNU_SOURCE 1
22#endif
95ee490b 23#include <fcntl.h>
a7c36c83 24#include <libgen.h>
d659597e 25#include <stdint.h>
a7c36c83 26#include <stdio.h>
e6294545 27#include <string.h>
a7c36c83 28#include <sys/types.h>
d38dd64a 29#include <unistd.h>
1897e3bc 30
e6294545
CB
31#include <lxc/lxccontainer.h>
32
1897e3bc 33#include "arguments.h"
d38dd64a 34#include "config.h"
9c382925 35#include "log.h"
0e9dc035 36#include "storage_utils.h"
9c382925 37#include "utils.h"
38
39lxc_log_define(lxc_create, lxc);
1897e3bc 40
0e9dc035 41static int my_parser(struct lxc_arguments *args, int c, char *arg);
0e9dc035 42static void create_helpfn(const struct lxc_arguments *args);
43static bool validate_bdev_args(struct lxc_arguments *args);
1897e3bc
SH
44
45static const struct option my_longopts[] = {
46 {"bdev", required_argument, 0, 'B'},
47 {"config", required_argument, 0, 'f'},
48 {"template", required_argument, 0, 't'},
49 {"lvname", required_argument, 0, '0'},
50 {"vgname", required_argument, 0, '1'},
f99c386b
SS
51 {"thinpool", required_argument, 0, '2'},
52 {"fstype", required_argument, 0, '3'},
53 {"fssize", required_argument, 0, '4'},
54 {"zfsroot", required_argument, 0, '5'},
55 {"dir", required_argument, 0, '6'},
7da812df
LB
56 {"rbdname", required_argument, 0, '7'},
57 {"rbdpool", required_argument, 0, '8'},
1897e3bc
SH
58 LXC_COMMON_OPTIONS
59};
60
61static struct lxc_arguments my_args = {
0e9dc035 62 .progname = "lxc-create",
63 .helpfn = create_helpfn,
64 .help = "\
0e40f65d 65--name=NAME --template=TEMPLATE [OPTION...] [-- template-options]\n\
1897e3bc 66\n\
3155e7f9 67lxc-create creates a container\n\
1897e3bc
SH
68\n\
69Options :\n\
2984ee36
KY
70 -n, --name=NAME NAME of the container\n\
71 -f, --config=CONFIG Initial configuration file\n\
72 -t, --template=TEMPLATE Template to use to setup container\n\
73 -B, --bdev=BDEV Backing store type to use\n\
74 --dir=DIR Place rootfs directory under DIR\n\
75\n\
76 BDEV options for LVM (with -B/--bdev lvm):\n\
77 --lvname=LVNAME Use LVM lv name LVNAME\n\
78 (Default: container name)\n\
79 --vgname=VG Use LVM vg called VG\n\
80 (Default: lxc)\n\
81 --thinpool=TP Use LVM thin pool called TP\n\
82 (Default: lxc)\n\
83\n\
84 BDEV options for Ceph RBD (with -B/--bdev rbd) :\n\
85 --rbdname=RBDNAME Use Ceph RBD name RBDNAME\n\
86 (Default: container name)\n\
87 --rbdpool=POOL Use Ceph RBD pool name POOL\n\
88 (Default: lxc)\n\
89\n\
90 BDEV option for ZFS (with -B/--bdev zfs) :\n\
91 --zfsroot=PATH Create zfs under given zfsroot\n\
92 (Default: tank/lxc)\n\
93\n\
94 BDEV options for LVM or Loop (with -B/--bdev lvm/loop) :\n\
95 --fstype=TYPE Create fstype TYPE\n\
13bc6113 96 (Default: ext4)\n\
2984ee36
KY
97 --fssize=SIZE[U] Create filesystem of\n\
98 size SIZE * unit U (bBkKmMgGtT)\n\
0e40f65d
AK
99 (Default: 1G, default unit: M)\n\
100 -- template-options\n\
101 This will pass template-options to the template as arguments.\n\
102 To see the list of options supported by the template,\n\
103 you can run lxc-create -t TEMPLATE -h.\n",
0e9dc035 104 .options = my_longopts,
105 .parser = my_parser,
106 .checker = NULL,
107 .log_priority = "ERROR",
108 .log_file = "none",
1897e3bc
SH
109};
110
0e9dc035 111static int my_parser(struct lxc_arguments *args, int c, char *arg)
112{
113 switch (c) {
114 case 'B':
115 args->bdevtype = arg;
116 break;
117 case 'f':
118 args->configfile = arg;
119 break;
120 case 't':
121 args->template = arg;
122 break;
123 case '0':
124 args->lvname = arg;
125 break;
126 case '1':
127 args->vgname = arg;
128 break;
129 case '2':
130 args->thinpool = arg;
131 break;
132 case '3':
133 args->fstype = arg;
134 break;
135 case '4':
136 args->fssize = get_fssize(arg);
137 break;
138 case '5':
139 args->zfsroot = arg;
140 break;
141 case '6':
142 args->dir = arg;
143 break;
144 case '7':
145 args->rbdname = arg;
146 break;
147 case '8':
148 args->rbdpool = arg;
149 break;
150 }
151 return 0;
152}
153
0e9dc035 154static void create_helpfn(const struct lxc_arguments *args)
155{
156 char *argv[3], *path;
157 pid_t pid;
158
159 if (!args->template)
160 return;
161
162 pid = fork();
163 if (pid) {
164 (void)wait_for_pid(pid);
165 return;
166 }
167
168 path = get_template_path(args->template);
169
170 argv[0] = path;
171 argv[1] = "-h";
172 argv[2] = NULL;
173
174 execv(path, argv);
175 ERROR("Error executing %s -h", path);
176 _exit(EXIT_FAILURE);
177}
178
179static bool validate_bdev_args(struct lxc_arguments *args)
1897e3bc 180{
0e9dc035 181 if (strncmp(args->bdevtype, "best", strlen(args->bdevtype)) != 0) {
182 if (args->fstype || args->fssize)
183 if (strncmp(args->bdevtype, "lvm", strlen(args->bdevtype)) != 0 &&
184 strncmp(args->bdevtype, "loop", strlen(args->bdevtype)) != 0 &&
185 strncmp(args->bdevtype, "rbd", strlen(args->bdevtype)) != 0) {
9c382925 186 ERROR("Filesystem type and size are only valid with block devices");
72e99249
SS
187 return false;
188 }
9c382925 189
0e9dc035 190 if (strncmp(args->bdevtype, "lvm", strlen(args->bdevtype)) != 0)
191 if (args->lvname || args->vgname || args->thinpool) {
9c382925 192 ERROR("--lvname, --vgname and --thinpool are only valid with -B lvm");
72e99249
SS
193 return false;
194 }
9c382925 195
0e9dc035 196 if (strncmp(args->bdevtype, "rbd", strlen(args->bdevtype)) != 0)
197 if (args->rbdname || args->rbdpool) {
9c382925 198 ERROR("--rbdname and --rbdpool are only valid with -B rbd");
7da812df
LB
199 return false;
200 }
9c382925 201
0e9dc035 202 if (strncmp(args->bdevtype, "zfs", strlen(args->bdevtype)) != 0)
203 if (args->zfsroot) {
9c382925 204 ERROR("zfsroot is only valid with -B zfs");
72e99249
SS
205 return false;
206 }
1897e3bc 207 }
9c382925 208
1897e3bc
SH
209 return true;
210}
211
1897e3bc
SH
212int main(int argc, char *argv[])
213{
214 struct lxc_container *c;
215 struct bdev_specs spec;
73b910a3 216 struct lxc_log log;
dc23c1c8 217 int flags = 0;
1897e3bc 218
1897e3bc 219 if (lxc_arguments_parse(&my_args, argc, argv))
a7c36c83 220 exit(EXIT_FAILURE);
1897e3bc 221
0e9dc035 222 log.name = my_args.name;
223 log.file = my_args.log_file;
224 log.level = my_args.log_priority;
225 log.prefix = my_args.progname;
226 log.quiet = my_args.quiet;
227 log.lxcpath = my_args.lxcpath[0];
228
229 if (lxc_log_init(&log))
230 exit(EXIT_FAILURE);
1897e3bc 231
d3de16bb 232 if (!my_args.template) {
77e5da8e 233 ERROR("A template must be specified");
234 ERROR("Use \"none\" if you really want a container without a rootfs");
a7c36c83 235 exit(EXIT_FAILURE);
d3de16bb
SG
236 }
237
77e5da8e 238 if (strncmp(my_args.template, "none", strlen(my_args.template)) == 0)
d3de16bb
SG
239 my_args.template = NULL;
240
1897e3bc
SH
241 if (!my_args.bdevtype)
242 my_args.bdevtype = "_unset";
a7c36c83 243
1897e3bc 244 if (!validate_bdev_args(&my_args))
a7c36c83 245 exit(EXIT_FAILURE);
1897e3bc 246
77e5da8e 247 if (strncmp(my_args.bdevtype, "none", strlen(my_args.bdevtype)) == 0)
50040b5e
SH
248 my_args.bdevtype = "dir";
249
1a0e70ac 250 /* Final check whether the user gave use a valid bdev type. */
77e5da8e 251 if (strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) != 0 &&
252 strncmp(my_args.bdevtype, "_unset", strlen(my_args.bdevtype)) != 0 &&
10bc1861 253 !is_valid_storage_type(my_args.bdevtype)) {
77e5da8e 254 ERROR("%s is not a valid backing storage type", my_args.bdevtype);
a7c36c83
CB
255 exit(EXIT_FAILURE);
256 }
257
49938fbc
CB
258 if (!my_args.lxcpath[0])
259 my_args.lxcpath[0] = lxc_get_global_config_item("lxc.lxcpath");
260
261 if (mkdir_p(my_args.lxcpath[0], 0755))
262 exit(EXIT_FAILURE);
78633423 263
49938fbc 264 if (geteuid())
37180208 265 if (access(my_args.lxcpath[0], O_RDONLY) < 0) {
9c382925 266 ERROR("You lack access to %s", my_args.lxcpath[0]);
a7c36c83 267 exit(EXIT_FAILURE);
460bcbd8 268 }
460bcbd8 269
1897e3bc
SH
270 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
271 if (!c) {
77e5da8e 272 ERROR("Failed to create lxc container");
a7c36c83 273 exit(EXIT_FAILURE);
1897e3bc 274 }
9c382925 275
1897e3bc 276 if (c->is_defined(c)) {
a7c36c83 277 lxc_container_put(c);
9c382925 278 ERROR("Container already exists");
a7c36c83 279 exit(EXIT_FAILURE);
1897e3bc 280 }
9c382925 281
1897e3bc
SH
282 if (my_args.configfile)
283 c->load_config(c, my_args.configfile);
284 else
e6294545 285 c->load_config(c, lxc_get_global_config_item("lxc.default_config"));
1897e3bc 286
9c382925 287 memset(&spec, 0, sizeof(spec));
288
72e99249
SS
289 if (my_args.fstype)
290 spec.fstype = my_args.fstype;
9c382925 291
72e99249
SS
292 if (my_args.fssize)
293 spec.fssize = my_args.fssize;
294
77e5da8e 295 if ((strncmp(my_args.bdevtype, "zfs", strlen(my_args.bdevtype)) == 0) ||
0e9dc035 296 (strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0))
1897e3bc 297 if (my_args.zfsroot)
72e99249 298 spec.zfs.zfsroot = my_args.zfsroot;
a7c36c83 299
77e5da8e 300 if ((strncmp(my_args.bdevtype, "lvm", strlen(my_args.bdevtype)) == 0) ||
0e9dc035 301 (strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
1897e3bc 302 if (my_args.lvname)
72e99249 303 spec.lvm.lv = my_args.lvname;
9c382925 304
1897e3bc 305 if (my_args.vgname)
72e99249 306 spec.lvm.vg = my_args.vgname;
9c382925 307
f99c386b 308 if (my_args.thinpool)
72e99249
SS
309 spec.lvm.thinpool = my_args.thinpool;
310 }
a7c36c83 311
77e5da8e 312 if ((strncmp(my_args.bdevtype, "rbd", strlen(my_args.bdevtype)) == 0) ||
0e9dc035 313 (strncmp(my_args.bdevtype, "best", strlen(my_args.bdevtype)) == 0)) {
7da812df
LB
314 if (my_args.rbdname)
315 spec.rbd.rbdname = my_args.rbdname;
9c382925 316
7da812df
LB
317 if (my_args.rbdpool)
318 spec.rbd.rbdpool = my_args.rbdpool;
319 }
a7c36c83
CB
320
321 if (my_args.dir)
7bb87886 322 spec.dir = my_args.dir;
1897e3bc 323
77e5da8e 324 if (strncmp(my_args.bdevtype, "_unset", strlen(my_args.bdevtype)) == 0)
1897e3bc 325 my_args.bdevtype = NULL;
a7c36c83 326
dc23c1c8
SH
327 if (my_args.quiet)
328 flags = LXC_CREATE_QUIET;
a7c36c83 329
dc23c1c8 330 if (!c->create(c, my_args.template, my_args.bdevtype, &spec, flags, &argv[optind])) {
0e9dc035 331 ERROR("Failed to create container %s", c->name);
1897e3bc 332 lxc_container_put(c);
a7c36c83 333 exit(EXIT_FAILURE);
1897e3bc 334 }
a7c36c83
CB
335
336 lxc_container_put(c);
a7c36c83 337 exit(EXIT_SUCCESS);
1897e3bc 338}