]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_create.c
3 * Copyright © 2013 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2013 Canonical Ltd.
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.
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.
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.
27 #include <sys/types.h>
29 #include <lxc/lxccontainer.h>
31 #include "arguments.h"
32 #include "tool_utils.h"
34 static uint64_t get_fssize(char *s
)
39 ret
= strtoull(s
, &end
, 0);
42 fprintf(stderr
, "Invalid blockdev size '%s', using default size\n", s
);
48 ret
*= 1024ULL * 1024ULL; /* MB by default */
49 else if (*end
== 'b' || *end
== 'B')
51 else if (*end
== 'k' || *end
== 'K')
53 else if (*end
== 'm' || *end
== 'M')
54 ret
*= 1024ULL * 1024ULL;
55 else if (*end
== 'g' || *end
== 'G')
56 ret
*= 1024ULL * 1024ULL * 1024ULL;
57 else if (*end
== 't' || *end
== 'T')
58 ret
*= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
61 fprintf(stderr
, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end
, s
);
67 static int my_parser(struct lxc_arguments
* args
, int c
, char* arg
)
70 case 'B': args
->bdevtype
= arg
; break;
71 case 'f': args
->configfile
= arg
; break;
72 case 't': args
->template = arg
; break;
73 case '0': args
->lvname
= arg
; break;
74 case '1': args
->vgname
= arg
; break;
75 case '2': args
->thinpool
= arg
; break;
76 case '3': args
->fstype
= arg
; break;
77 case '4': args
->fssize
= get_fssize(arg
); break;
78 case '5': args
->zfsroot
= arg
; break;
79 case '6': args
->dir
= arg
; break;
80 case '7': args
->rbdname
= arg
; break;
81 case '8': args
->rbdpool
= arg
; break;
86 static const struct option my_longopts
[] = {
87 {"bdev", required_argument
, 0, 'B'},
88 {"config", required_argument
, 0, 'f'},
89 {"template", required_argument
, 0, 't'},
90 {"lvname", required_argument
, 0, '0'},
91 {"vgname", required_argument
, 0, '1'},
92 {"thinpool", required_argument
, 0, '2'},
93 {"fstype", required_argument
, 0, '3'},
94 {"fssize", required_argument
, 0, '4'},
95 {"zfsroot", required_argument
, 0, '5'},
96 {"dir", required_argument
, 0, '6'},
97 {"rbdname", required_argument
, 0, '7'},
98 {"rbdpool", required_argument
, 0, '8'},
102 static void create_helpfn(const struct lxc_arguments
*args
)
104 char *argv
[3], *path
;
116 path
= get_template_path(args
->template);
123 fprintf(stderr
, "Error executing %s -h\n", path
);
127 static struct lxc_arguments my_args
= {
128 .progname
= "lxc-create",
129 .helpfn
= create_helpfn
,
131 --name=NAME --template=TEMPLATE [OPTION...]\n\
133 lxc-create creates a container\n\
136 -n, --name=NAME NAME of the container\n\
137 -f, --config=CONFIG Initial configuration file\n\
138 -t, --template=TEMPLATE Template to use to setup container\n\
139 -B, --bdev=BDEV Backing store type to use\n\
140 --dir=DIR Place rootfs directory under DIR\n\
142 BDEV options for LVM (with -B/--bdev lvm):\n\
143 --lvname=LVNAME Use LVM lv name LVNAME\n\
144 (Default: container name)\n\
145 --vgname=VG Use LVM vg called VG\n\
147 --thinpool=TP Use LVM thin pool called TP\n\
150 BDEV options for Ceph RBD (with -B/--bdev rbd) :\n\
151 --rbdname=RBDNAME Use Ceph RBD name RBDNAME\n\
152 (Default: container name)\n\
153 --rbdpool=POOL Use Ceph RBD pool name POOL\n\
156 BDEV option for ZFS (with -B/--bdev zfs) :\n\
157 --zfsroot=PATH Create zfs under given zfsroot\n\
158 (Default: tank/lxc)\n\
160 BDEV options for LVM or Loop (with -B/--bdev lvm/loop) :\n\
161 --fstype=TYPE Create fstype TYPE\n\
163 --fssize=SIZE[U] Create filesystem of\n\
164 size SIZE * unit U (bBkKmMgGtT)\n\
165 (Default: 1G, default unit: M)\n",
166 .options
= my_longopts
,
171 static bool validate_bdev_args(struct lxc_arguments
*a
)
173 if (strcmp(a
->bdevtype
, "best") != 0) {
174 if (a
->fstype
|| a
->fssize
) {
175 if (strcmp(a
->bdevtype
, "lvm") != 0 &&
176 strcmp(a
->bdevtype
, "loop") != 0 &&
177 strcmp(a
->bdevtype
, "rbd") != 0) {
178 fprintf(stderr
, "filesystem type and size are only valid with block devices\n");
182 if (strcmp(a
->bdevtype
, "lvm") != 0) {
183 if (a
->lvname
|| a
->vgname
|| a
->thinpool
) {
184 fprintf(stderr
, "--lvname, --vgname and --thinpool are only valid with -B lvm\n");
188 if (strcmp(a
->bdevtype
, "rbd") != 0) {
189 if (a
->rbdname
|| a
->rbdpool
) {
190 fprintf(stderr
, "--rbdname and --rbdpool are only valid with -B rbd\n");
194 if (strcmp(a
->bdevtype
, "zfs") != 0) {
196 fprintf(stderr
, "zfsroot is only valid with -B zfs\n");
204 static bool is_valid_storage_type(const char *type
)
206 if (strcmp(type
, "dir") == 0 ||
207 strcmp(type
, "btrfs") == 0 ||
208 strcmp(type
, "loop") == 0 ||
209 strcmp(type
, "lvm") == 0 ||
210 strcmp(type
, "nbd") == 0 ||
211 strcmp(type
, "overlay") == 0 ||
212 strcmp(type
, "overlayfs") == 0 ||
213 strcmp(type
, "rbd") == 0 ||
214 strcmp(type
, "zfs") == 0)
220 int main(int argc
, char *argv
[])
222 struct lxc_container
*c
;
223 struct bdev_specs spec
;
227 if (lxc_arguments_parse(&my_args
, argc
, argv
))
230 if (!my_args
.log_file
)
231 my_args
.log_file
= "none";
233 log
.name
= my_args
.name
;
234 log
.file
= my_args
.log_file
;
235 log
.level
= my_args
.log_priority
;
236 log
.prefix
= my_args
.progname
;
237 log
.quiet
= my_args
.quiet
;
238 log
.lxcpath
= my_args
.lxcpath
[0];
240 if (lxc_log_init(&log
))
243 if (!my_args
.template) {
244 fprintf(stderr
, "A template must be specified.\n");
245 fprintf(stderr
, "Use \"none\" if you really want a container without a rootfs.\n");
249 if (strcmp(my_args
.template, "none") == 0)
250 my_args
.template = NULL
;
252 memset(&spec
, 0, sizeof(spec
));
253 if (!my_args
.bdevtype
)
254 my_args
.bdevtype
= "_unset";
256 if (!validate_bdev_args(&my_args
))
259 if (strcmp(my_args
.bdevtype
, "none") == 0)
260 my_args
.bdevtype
= "dir";
262 /* Final check whether the user gave use a valid bdev type. */
263 if (strcmp(my_args
.bdevtype
, "best") &&
264 strcmp(my_args
.bdevtype
, "_unset") &&
265 !is_valid_storage_type(my_args
.bdevtype
)) {
266 fprintf(stderr
, "%s is not a valid backing storage type.\n", my_args
.bdevtype
);
271 if (mkdir_p(my_args
.lxcpath
[0], 0755)) {
274 if (access(my_args
.lxcpath
[0], O_RDONLY
) < 0) {
275 fprintf(stderr
, "You lack access to %s\n", my_args
.lxcpath
[0]);
278 if (strcmp(my_args
.bdevtype
, "dir") && strcmp(my_args
.bdevtype
, "_unset") &&
279 strcmp(my_args
.bdevtype
, "btrfs")) {
280 fprintf(stderr
, "Unprivileged users cannot create %s containers.\n", my_args
.bdevtype
);
286 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
288 fprintf(stderr
, "Failed to create lxc container.\n");
291 if (c
->is_defined(c
)) {
292 lxc_container_put(c
);
293 fprintf(stderr
, "Container already exists\n");
296 if (my_args
.configfile
)
297 c
->load_config(c
, my_args
.configfile
);
299 c
->load_config(c
, lxc_get_global_config_item("lxc.default_config"));
302 spec
.fstype
= my_args
.fstype
;
304 spec
.fssize
= my_args
.fssize
;
306 if ((strcmp(my_args
.bdevtype
, "zfs") == 0) || (strcmp(my_args
.bdevtype
, "best") == 0)) {
308 spec
.zfs
.zfsroot
= my_args
.zfsroot
;
311 if ((strcmp(my_args
.bdevtype
, "lvm") == 0) || (strcmp(my_args
.bdevtype
, "best") == 0)) {
313 spec
.lvm
.lv
= my_args
.lvname
;
315 spec
.lvm
.vg
= my_args
.vgname
;
316 if (my_args
.thinpool
)
317 spec
.lvm
.thinpool
= my_args
.thinpool
;
320 if ((strcmp(my_args
.bdevtype
, "rbd") == 0) || (strcmp(my_args
.bdevtype
, "best") == 0)) {
322 spec
.rbd
.rbdname
= my_args
.rbdname
;
324 spec
.rbd
.rbdpool
= my_args
.rbdpool
;
328 spec
.dir
= my_args
.dir
;
330 if (strcmp(my_args
.bdevtype
, "_unset") == 0)
331 my_args
.bdevtype
= NULL
;
334 flags
= LXC_CREATE_QUIET
;
336 if (!c
->create(c
, my_args
.template, my_args
.bdevtype
, &spec
, flags
, &argv
[optind
])) {
337 fprintf(stderr
, "Error creating container %s\n", c
->name
);
338 lxc_container_put(c
);
342 lxc_container_put(c
);