]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_create.c
Define LXC_DEFAULT_CONFIG
[mirror_lxc.git] / src / lxc / lxc_create.c
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
20 #include "../lxc/lxccontainer.h"
21
22 #include <stdio.h>
23 #include <libgen.h>
24 #include <unistd.h>
25 #include <ctype.h>
26 #include <sys/types.h>
27
28 #include <lxc/lxc.h>
29 #include <lxc/log.h>
30 #include <lxc/bdev.h>
31
32 #include "arguments.h"
33 #include "utils.h"
34
35 lxc_log_define(lxc_create, lxc);
36
37 /* we pass fssize in bytes */
38 static unsigned long get_fssize(char *s)
39 {
40 unsigned long ret;
41 char *end;
42
43 ret = strtoul(s, &end, 0);
44 if (end == s)
45 return 0;
46 while (isblank(*end))
47 end++;
48 if (!(*end))
49 return ret;
50 if (*end == 'g' || *end == 'G')
51 ret *= 1000000000;
52 else if (*end == 'm' || *end == 'M')
53 ret *= 1000000;
54 else if (*end == 'k' || *end == 'K')
55 ret *= 1000;
56 return ret;
57 }
58
59 static int my_parser(struct lxc_arguments* args, int c, char* arg)
60 {
61 switch (c) {
62 case 'B': args->bdevtype = arg; break;
63 case 'f': args->configfile = arg; break;
64 case 't': args->template = arg; break;
65 case '0': args->lvname = arg; break;
66 case '1': args->vgname = arg; break;
67 case '2': args->fstype = arg; break;
68 case '3': args->fssize = get_fssize(arg); break;
69 case '4': args->zfsroot = arg; break;
70 case '5': args->dir = arg; break;
71 }
72 return 0;
73 }
74
75 static const struct option my_longopts[] = {
76 {"bdev", required_argument, 0, 'B'},
77 {"config", required_argument, 0, 'f'},
78 {"template", required_argument, 0, 't'},
79 {"lvname", required_argument, 0, '0'},
80 {"vgname", required_argument, 0, '1'},
81 {"fstype", required_argument, 0, '2'},
82 {"fssize", required_argument, 0, '3'},
83 {"zfsroot", required_argument, 0, '4'},
84 {"dir", required_argument, 0, '5'},
85 LXC_COMMON_OPTIONS
86 };
87
88 static struct lxc_arguments my_args = {
89 .progname = "lxc-create",
90 .help = "\
91 --name=NAME [-w] [-r] [-t timeout] [-P lxcpath]\n\
92 \n\
93 lxc-creae creates a container\n\
94 \n\
95 Options :\n\
96 -n, --name=NAME NAME for name of the container\n\
97 -f, --config=file initial configuration file\n\
98 -t, --template=t template to use to setup container\n\
99 -B, --bdev=BDEV backing store type to use\n\
100 --lxcpath=PATH place container under PATH\n\
101 --lvname=LVNAME Use LVM lv name LVNAME\n\
102 (Default: container name)\n\
103 --vgname=VG Use LVM vg called VG\n\
104 (Default: lxc))\n\
105 --fstype=TYPE Create fstype TYPE\n\
106 (Default: ext3))\n\
107 --fssize=SIZE Create filesystem of size SIZE\n\
108 (Default: 1G))\n\
109 --dir=DIR Place rootfs directory under DIR\n\
110 --zfsroot=PATH Create zfs under given zfsroot\n\
111 (Default: tank/lxc))\n",
112 .options = my_longopts,
113 .parser = my_parser,
114 .checker = NULL,
115 };
116
117 bool validate_bdev_args(struct lxc_arguments *a)
118 {
119 if (strcmp(a->bdevtype, "lvm") != 0) {
120 if (a->fstype || a->fssize) {
121 fprintf(stderr, "filesystem type and size are only valid with block devices\n");
122 return false;
123 }
124 if (a->lvname || a->vgname) {
125 fprintf(stderr, "--lvname and --vgname are only valid with -B lvm\n");
126 return false;
127 }
128 }
129 if (strcmp(a->bdevtype, "zfs") != 0) {
130 if (a->zfsroot) {
131 fprintf(stderr, "zfsroot is only valid with -B zfs\n");
132 return false;
133 }
134 }
135 return true;
136 }
137
138 int main(int argc, char *argv[])
139 {
140 struct lxc_container *c;
141 struct bdev_specs spec;
142
143 /* this is a short term test. We'll probably want to check for
144 * write access to lxcpath instead */
145 if (geteuid()) {
146 fprintf(stderr, "%s must be run as root\n", argv[0]);
147 exit(1);
148 }
149
150 if (lxc_arguments_parse(&my_args, argc, argv))
151 exit(1);
152
153 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
154 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
155 exit(1);
156
157 memset(&spec, 0, sizeof(spec));
158 if (!my_args.bdevtype)
159 my_args.bdevtype = "_unset";
160 if (!validate_bdev_args(&my_args))
161 exit(1);
162
163 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
164 if (!c) {
165 fprintf(stderr, "System error loading container\n");
166 exit(1);
167 }
168 if (c->is_defined(c)) {
169 fprintf(stderr, "Container already exists\n");
170 exit(1);
171 }
172 if (my_args.configfile)
173 c->load_config(c, my_args.configfile);
174 else
175 c->load_config(c, LXC_DEFAULT_CONFIG);
176
177 if (strcmp(my_args.bdevtype, "zfs") == 0) {
178 if (my_args.zfsroot)
179 spec.u.zfs.zfsroot = my_args.zfsroot;
180 } else if (strcmp(my_args.bdevtype, "lvm") == 0) {
181 if (my_args.lvname)
182 spec.u.lvm.lv = my_args.lvname;
183 if (my_args.vgname)
184 spec.u.lvm.vg = my_args.vgname;
185 if (my_args.fstype)
186 spec.u.lvm.fstype = my_args.fstype;
187 if (my_args.fssize)
188 spec.u.lvm.fssize = my_args.fssize;
189 } else if (my_args.dir) {
190 ERROR("--dir is not yet supported");
191 exit(1);
192 }
193
194 if (strcmp(my_args.bdevtype, "_unset") == 0)
195 my_args.bdevtype = NULL;
196 if (!c->create(c, my_args.template, my_args.bdevtype, &spec, &argv[optind])) {
197 ERROR("Error creating container %s", c->name);
198 lxc_container_put(c);
199 exit(1);
200 }
201 INFO("container %s created", c->name);
202 exit(0);
203 }