]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_create.c
1 /* SPDX-License-Identifier: GPL-2.0-only */
11 #include <sys/types.h>
16 #include "arguments.h"
19 #include "storage_utils.h"
22 lxc_log_define(lxc_create
, lxc
);
24 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
);
25 static void create_helpfn(const struct lxc_arguments
*args
);
26 static bool validate_bdev_args(struct lxc_arguments
*args
);
28 static const struct option my_longopts
[] = {
29 {"bdev", required_argument
, 0, 'B'},
30 {"config", required_argument
, 0, 'f'},
31 {"template", required_argument
, 0, 't'},
32 {"lvname", required_argument
, 0, '0'},
33 {"vgname", required_argument
, 0, '1'},
34 {"thinpool", required_argument
, 0, '2'},
35 {"fstype", required_argument
, 0, '3'},
36 {"fssize", required_argument
, 0, '4'},
37 {"zfsroot", required_argument
, 0, '5'},
38 {"dir", required_argument
, 0, '6'},
39 {"rbdname", required_argument
, 0, '7'},
40 {"rbdpool", required_argument
, 0, '8'},
44 static struct lxc_arguments my_args
= {
45 .progname
= "lxc-create",
46 .helpfn
= create_helpfn
,
48 --name=NAME --template=TEMPLATE [OPTION...] [-- template-options]\n\
50 lxc-create creates a container\n\
53 -n, --name=NAME NAME of the container\n\
54 -f, --config=CONFIG Initial configuration file\n\
55 -t, --template=TEMPLATE Template to use to setup container\n\
56 -B, --bdev=BDEV Backing store type to use\n\
57 --dir=DIR Place rootfs directory under DIR\n\
59 BDEV options for LVM (with -B/--bdev lvm):\n\
60 --lvname=LVNAME Use LVM lv name LVNAME\n\
61 (Default: container name)\n\
62 --vgname=VG Use LVM vg called VG\n\
64 --thinpool=TP Use LVM thin pool called TP\n\
67 BDEV options for Ceph RBD (with -B/--bdev rbd) :\n\
68 --rbdname=RBDNAME Use Ceph RBD name RBDNAME\n\
69 (Default: container name)\n\
70 --rbdpool=POOL Use Ceph RBD pool name POOL\n\
73 BDEV option for ZFS (with -B/--bdev zfs) :\n\
74 --zfsroot=PATH Create zfs under given zfsroot\n\
75 (Default: tank/lxc)\n\
77 BDEV options for LVM or Loop (with -B/--bdev lvm/loop) :\n\
78 --fstype=TYPE Create fstype TYPE\n\
80 --fssize=SIZE[U] Create filesystem of\n\
81 size SIZE * unit U (bBkKmMgGtT)\n\
82 (Default: 1G, default unit: M)\n\
83 -- template-options\n\
84 This will pass template-options to the template as arguments.\n\
85 To see the list of options supported by the template,\n\
86 you can run lxc-create -t TEMPLATE -h.\n",
87 .options
= my_longopts
,
90 .log_priority
= "ERROR",
94 static int my_parser(struct lxc_arguments
*args
, int c
, char *arg
)
101 args
->configfile
= arg
;
104 args
->template = arg
;
113 args
->thinpool
= arg
;
119 args
->fssize
= get_fssize(arg
);
137 static void create_helpfn(const struct lxc_arguments
*args
)
139 char *argv
[3], *path
;
147 (void)wait_for_pid(pid
);
151 path
= get_template_path(args
->template);
158 ERROR("Error executing %s -h", path
);
162 static bool validate_bdev_args(struct lxc_arguments
*args
)
164 if (strncmp(args
->bdevtype
, "best", strlen(args
->bdevtype
)) != 0) {
165 if (args
->fstype
|| args
->fssize
)
166 if (strncmp(args
->bdevtype
, "lvm", strlen(args
->bdevtype
)) != 0 &&
167 strncmp(args
->bdevtype
, "loop", strlen(args
->bdevtype
)) != 0 &&
168 strncmp(args
->bdevtype
, "rbd", strlen(args
->bdevtype
)) != 0) {
169 ERROR("Filesystem type and size are only valid with block devices");
173 if (strncmp(args
->bdevtype
, "lvm", strlen(args
->bdevtype
)) != 0)
174 if (args
->lvname
|| args
->vgname
|| args
->thinpool
) {
175 ERROR("--lvname, --vgname and --thinpool are only valid with -B lvm");
179 if (strncmp(args
->bdevtype
, "rbd", strlen(args
->bdevtype
)) != 0)
180 if (args
->rbdname
|| args
->rbdpool
) {
181 ERROR("--rbdname and --rbdpool are only valid with -B rbd");
185 if (strncmp(args
->bdevtype
, "zfs", strlen(args
->bdevtype
)) != 0)
187 ERROR("zfsroot is only valid with -B zfs");
195 int main(int argc
, char *argv
[])
197 struct lxc_container
*c
;
198 struct bdev_specs spec
;
202 if (lxc_arguments_parse(&my_args
, argc
, argv
))
205 log
.name
= my_args
.name
;
206 log
.file
= my_args
.log_file
;
207 log
.level
= my_args
.log_priority
;
208 log
.prefix
= my_args
.progname
;
209 log
.quiet
= my_args
.quiet
;
210 log
.lxcpath
= my_args
.lxcpath
[0];
212 if (lxc_log_init(&log
))
215 if (!my_args
.template) {
216 ERROR("A template must be specified");
217 ERROR("Use \"none\" if you really want a container without a rootfs");
221 if (my_args
.dir
&& my_args
.dir
[0] != '/') {
222 ERROR("--dir should use absolute path");
226 if (strncmp(my_args
.template, "none", strlen(my_args
.template)) == 0)
227 my_args
.template = NULL
;
229 if (!my_args
.bdevtype
)
230 my_args
.bdevtype
= "_unset";
232 if (!validate_bdev_args(&my_args
))
235 if (strncmp(my_args
.bdevtype
, "none", strlen(my_args
.bdevtype
)) == 0)
236 my_args
.bdevtype
= "dir";
238 /* Final check whether the user gave use a valid bdev type. */
239 if (strncmp(my_args
.bdevtype
, "best", strlen(my_args
.bdevtype
)) != 0 &&
240 strncmp(my_args
.bdevtype
, "_unset", strlen(my_args
.bdevtype
)) != 0 &&
241 !is_valid_storage_type(my_args
.bdevtype
)) {
242 ERROR("%s is not a valid backing storage type", my_args
.bdevtype
);
246 if (!my_args
.lxcpath
[0])
247 my_args
.lxcpath
[0] = lxc_get_global_config_item("lxc.lxcpath");
249 if (mkdir_p(my_args
.lxcpath
[0], 0755))
253 if (access(my_args
.lxcpath
[0], O_RDONLY
) < 0) {
254 ERROR("You lack access to %s", my_args
.lxcpath
[0]);
258 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
260 ERROR("Failed to create lxc container");
264 if (c
->is_defined(c
)) {
265 lxc_container_put(c
);
266 ERROR("Container already exists");
270 if (my_args
.configfile
)
271 c
->load_config(c
, my_args
.configfile
);
273 c
->load_config(c
, lxc_get_global_config_item("lxc.default_config"));
275 memset(&spec
, 0, sizeof(spec
));
278 spec
.fstype
= my_args
.fstype
;
281 spec
.fssize
= my_args
.fssize
;
283 if ((strncmp(my_args
.bdevtype
, "zfs", strlen(my_args
.bdevtype
)) == 0) ||
284 (strncmp(my_args
.bdevtype
, "best", strlen(my_args
.bdevtype
)) == 0))
286 spec
.zfs
.zfsroot
= my_args
.zfsroot
;
288 if ((strncmp(my_args
.bdevtype
, "lvm", strlen(my_args
.bdevtype
)) == 0) ||
289 (strncmp(my_args
.bdevtype
, "best", strlen(my_args
.bdevtype
)) == 0)) {
291 spec
.lvm
.lv
= my_args
.lvname
;
294 spec
.lvm
.vg
= my_args
.vgname
;
296 if (my_args
.thinpool
)
297 spec
.lvm
.thinpool
= my_args
.thinpool
;
300 if ((strncmp(my_args
.bdevtype
, "rbd", strlen(my_args
.bdevtype
)) == 0) ||
301 (strncmp(my_args
.bdevtype
, "best", strlen(my_args
.bdevtype
)) == 0)) {
303 spec
.rbd
.rbdname
= my_args
.rbdname
;
306 spec
.rbd
.rbdpool
= my_args
.rbdpool
;
310 spec
.dir
= my_args
.dir
;
312 if (strncmp(my_args
.bdevtype
, "_unset", strlen(my_args
.bdevtype
)) == 0)
313 my_args
.bdevtype
= NULL
;
316 flags
= LXC_CREATE_QUIET
;
318 if (!c
->create(c
, my_args
.template, my_args
.bdevtype
, &spec
, flags
, &argv
[optind
])) {
319 ERROR("Failed to create container %s", c
->name
);
320 lxc_container_put(c
);
324 lxc_container_put(c
);