]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/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.
20 #include <lxc/lxccontainer.h>
27 #include <sys/types.h>
33 #include "arguments.h"
36 lxc_log_define(lxc_create_ui
, lxc
);
38 static uint64_t get_fssize(char *s
)
43 ret
= strtoull(s
, &end
, 0);
46 fprintf(stderr
, "Invalid blockdev size '%s', using default size\n", s
);
52 ret
*= 1024ULL * 1024ULL; // MB by default
53 else if (*end
== 'b' || *end
== 'B')
55 else if (*end
== 'k' || *end
== 'K')
57 else if (*end
== 'm' || *end
== 'M')
58 ret
*= 1024ULL * 1024ULL;
59 else if (*end
== 'g' || *end
== 'G')
60 ret
*= 1024ULL * 1024ULL * 1024ULL;
61 else if (*end
== 't' || *end
== 'T')
62 ret
*= 1024ULL * 1024ULL * 1024ULL * 1024ULL;
65 fprintf(stderr
, "Invalid blockdev unit size '%c' in '%s', using default size\n", *end
, s
);
71 static int my_parser(struct lxc_arguments
* args
, int c
, char* arg
)
74 case 'B': args
->bdevtype
= arg
; break;
75 case 'f': args
->configfile
= arg
; break;
76 case 't': args
->template = arg
; break;
77 case '0': args
->lvname
= arg
; break;
78 case '1': args
->vgname
= arg
; break;
79 case '2': args
->thinpool
= arg
; break;
80 case '3': args
->fstype
= arg
; break;
81 case '4': args
->fssize
= get_fssize(arg
); break;
82 case '5': args
->zfsroot
= arg
; break;
83 case '6': args
->dir
= arg
; break;
88 static const struct option my_longopts
[] = {
89 {"bdev", required_argument
, 0, 'B'},
90 {"config", required_argument
, 0, 'f'},
91 {"template", required_argument
, 0, 't'},
92 {"lvname", required_argument
, 0, '0'},
93 {"vgname", required_argument
, 0, '1'},
94 {"thinpool", required_argument
, 0, '2'},
95 {"fstype", required_argument
, 0, '3'},
96 {"fssize", required_argument
, 0, '4'},
97 {"zfsroot", required_argument
, 0, '5'},
98 {"dir", required_argument
, 0, '6'},
102 static void create_helpfn(const struct lxc_arguments
*args
) {
103 char *argv
[3], *path
;
115 path
= get_template_path(args
->template);
121 ERROR("Error executing %s -h", path
);
125 static struct lxc_arguments my_args
= {
126 .progname
= "lxc-create",
127 .helpfn
= create_helpfn
,
129 --name=NAME -t template [-w] [-r] [-P lxcpath]\n\
131 lxc-create creates a container\n\
134 -n, --name=NAME NAME of the container\n\
135 -f, --config=file Initial configuration file\n\
136 -t, --template=t Template to use to setup container\n\
137 -B, --bdev=BDEV Backing store type to use\n\
138 -P, --lxcpath=PATH Place container under PATH\n\
139 --lvname=LVNAME Use LVM lv name LVNAME\n\
140 (Default: container name)\n\
141 --vgname=VG Use LVM vg called VG\n\
143 --thinpool=TP Use LVM thin pool called TP\n\
145 --fstype=TYPE Create fstype TYPE\n\
147 --fssize=SIZE[U] Create filesystem of size SIZE * unit U (bBkKmMgGtT)\n\
148 (Default: 1G, default unit: M)\n\
149 --dir=DIR Place rootfs directory under DIR\n\
150 --zfsroot=PATH Create zfs under given zfsroot\n\
151 (Default: tank/lxc)\n",
152 .options
= my_longopts
,
157 static bool validate_bdev_args(struct lxc_arguments
*a
)
159 if (strcmp(a
->bdevtype
, "best") != 0) {
160 if (a
->fstype
|| a
->fssize
) {
161 if (strcmp(a
->bdevtype
, "lvm") != 0 &&
162 strcmp(a
->bdevtype
, "loop") != 0) {
163 fprintf(stderr
, "filesystem type and size are only valid with block devices\n");
167 if (strcmp(a
->bdevtype
, "lvm") != 0) {
168 if (a
->lvname
|| a
->vgname
|| a
->thinpool
) {
169 fprintf(stderr
, "--lvname, --vgname and --thinpool are only valid with -B lvm\n");
173 if (strcmp(a
->bdevtype
, "zfs") != 0) {
175 fprintf(stderr
, "zfsroot is only valid with -B zfs\n");
183 int main(int argc
, char *argv
[])
185 struct lxc_container
*c
;
186 struct bdev_specs spec
;
189 if (lxc_arguments_parse(&my_args
, argc
, argv
))
192 if (!my_args
.log_file
)
193 my_args
.log_file
= "none";
195 if (lxc_log_init(my_args
.name
, my_args
.log_file
, my_args
.log_priority
,
196 my_args
.progname
, my_args
.quiet
, my_args
.lxcpath
[0]))
198 lxc_log_options_no_override();
200 if (!my_args
.template) {
201 fprintf(stderr
, "A template must be specified.\n");
202 fprintf(stderr
, "Use \"none\" if you really want a container without a rootfs.\n");
206 if (strcmp(my_args
.template, "none") == 0)
207 my_args
.template = NULL
;
209 memset(&spec
, 0, sizeof(spec
));
210 if (!my_args
.bdevtype
)
211 my_args
.bdevtype
= "_unset";
212 if (!validate_bdev_args(&my_args
))
215 if (strcmp(my_args
.bdevtype
, "none") == 0)
216 my_args
.bdevtype
= "dir";
219 if (mkdir_p(my_args
.lxcpath
[0], 0755)) {
222 if (access(my_args
.lxcpath
[0], O_RDWR
) < 0) {
223 fprintf(stderr
, "You lack access to %s\n", my_args
.lxcpath
[0]);
226 if (strcmp(my_args
.bdevtype
, "dir") && strcmp(my_args
.bdevtype
, "_unset") &&
227 strcmp(my_args
.bdevtype
, "btrfs")) {
228 fprintf(stderr
, "Unprivileged users cannot create %s containers", my_args
.bdevtype
);
234 c
= lxc_container_new(my_args
.name
, my_args
.lxcpath
[0]);
236 fprintf(stderr
, "System error loading container\n");
239 if (c
->is_defined(c
)) {
240 fprintf(stderr
, "Container already exists\n");
243 if (my_args
.configfile
)
244 c
->load_config(c
, my_args
.configfile
);
246 c
->load_config(c
, lxc_global_config_value("lxc.default_config"));
249 spec
.fstype
= my_args
.fstype
;
251 spec
.fssize
= my_args
.fssize
;
253 if (strcmp(my_args
.bdevtype
, "zfs") == 0 || strcmp(my_args
.bdevtype
, "best") == 0) {
255 spec
.zfs
.zfsroot
= my_args
.zfsroot
;
257 if (strcmp(my_args
.bdevtype
, "lvm") == 0 || strcmp(my_args
.bdevtype
, "best") == 0) {
259 spec
.lvm
.lv
= my_args
.lvname
;
261 spec
.lvm
.vg
= my_args
.vgname
;
262 if (my_args
.thinpool
)
263 spec
.lvm
.thinpool
= my_args
.thinpool
;
266 spec
.dir
= my_args
.dir
;
269 if (strcmp(my_args
.bdevtype
, "_unset") == 0)
270 my_args
.bdevtype
= NULL
;
272 flags
= LXC_CREATE_QUIET
;
273 if (!c
->create(c
, my_args
.template, my_args
.bdevtype
, &spec
, flags
, &argv
[optind
])) {
274 ERROR("Error creating container %s", c
->name
);
275 lxc_container_put(c
);
278 INFO("container %s created", c
->name
);