]> git.proxmox.com Git - dab.git/blame - dab
add support for ubuntu 18.04 (bionic beaver)
[dab.git] / dab
CommitLineData
8ab34b87
DM
1#!/usr/bin/perl -w
2
3use strict;
4use Getopt::Long;
5use PVE::DAB;
6
7$ENV{'LC_ALL'} = 'C';
8
9sub print_usage {
10 my ($msg) = @_;
11
12 if ($msg) {
13 print STDERR "ERROR: $msg\n";
14 }
15 print STDERR "dab <command> [parameters]\n";
16}
17
18
19if (scalar (@ARGV) == 0) {
20 print_usage ();
21 exit (-1);
22}
23
24my $cmdline = join (' ', @ARGV);
25
26my $cmd = shift @ARGV;
27
28if (!$cmd) {
29 print_usage("no command specified");
30 exit (-1);
31}
32
33my $dab = PVE::DAB->new();
34
35$dab->writelog ("dab: $cmdline\n");
36
37$SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
38 die "interrupted by signal\n";
39};
40
41eval {
42
43 if ($cmd eq 'init') {
44
45 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
46
47 $dab->initialize();
48
49 } elsif ($cmd eq 'bootstrap') {
50
51 my $opts = {};
52
53 if (!GetOptions ($opts, 'exim', 'minimal')) {
54 print_usage ();
55 exit (-1);
56 }
57
58 die "command 'bootstrap' expects no arguments.\n" if scalar (@ARGV) != 0;
59
60 $dab->ve_init();
61
62 $dab->bootstrap ($opts);
63
64 } elsif ($cmd eq 'finalize') {
65
66 my $opts = {};
67
68 if (!GetOptions ($opts, 'keepmycnf')) {
69 print_usage ();
70 exit (-1);
71 }
72
73 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
74
75 $dab->finalize($opts);
76
77 } elsif ($cmd eq 'veid') {
78
79 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
80
81 print $dab->{veid} . "\n";
82
83 } elsif ($cmd eq 'basedir') {
84
85 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
86
f0134ed2 87 print $dab->{rootfs} . "\n";
8ab34b87
DM
88
89 } elsif ($cmd eq 'packagefile') {
90
91 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
92
93 print "$dab->{targetname}.tar.gz\n";
94
95 } elsif ($cmd eq 'list') {
96
97 my $verbose;
98
99 if (!GetOptions ('verbose' =>\$verbose)) {
100 print_usage ();
101 exit (-1);
102 }
103
104 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
105
106 my $instpkgs = $dab->read_installed ();
107
108 foreach my $pkg (sort keys %$instpkgs) {
109 if ($verbose) {
110 my $version = $instpkgs->{$pkg}->{version};
111 print "$pkg $version\n";
112 } else {
113 print "$pkg\n";
114 }
115 }
116
117 } elsif ($cmd eq 'task') {
118
119 my $task = shift @ARGV;
120
121 if (!$task) {
122 print_usage ("no task specified");
123 exit (-1);
124 }
125
126 my $opts = {};
127
128 if ($task eq 'mysql') {
129
130 if (!GetOptions ($opts, 'password=s', 'start')) {
131 print_usage ();
132 exit (-1);
133 }
134
135 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
136
137 $dab->task_mysql ($opts);
138
139 } elsif ($task eq 'postgres') {
140
141 if (!GetOptions ($opts, 'version=s', 'start')) {
142 print_usage ();
143 exit (-1);
144 }
145
146 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
147
148 $dab->task_postgres ($opts);
149
150 } elsif ($task eq 'php') {
151
152 if (!GetOptions ($opts, 'memlimit=i')) {
153 print_usage ();
154 exit (-1);
155 }
156
157 die "task '$task' expects no arguments.\n" if scalar (@ARGV) != 0;
158
159 $dab->task_php ($opts);
160
161 } else {
162
163 print_usage ("unknown task '$task'");
164 exit (-1);
165
166 }
167
168 } elsif ($cmd eq 'install' || $cmd eq 'unpack') {
169
170 my $required;
171 foreach my $arg (@ARGV) {
172 if ($arg =~ m/\.pkglist$/) {
173 open (TMP, $arg) ||
174 die "cant open package list '$arg' - $!";
175 while (defined (my $line = <TMP>)) {
176 chomp $line;
177 next if $line =~ m/^\s*$/;
178 next if $line =~ m/\#/;
179 if ($line =~ m/^\s*(\S+)\s*$/) {
180 push @$required, $1;
181 } else {
182 die "invalid package name in '$arg' - $line\n";
183 }
184 }
185 } else {
186 push @$required, $arg;
187 }
188
189 close (TMP);
190 }
191
192 $dab->install ($required, $cmd eq 'unpack');
193
194 } elsif ($cmd eq 'exec') {
195
196 $dab->ve_exec (@ARGV);
197
198 } elsif ($cmd eq 'enter') {
199
200 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
201
202 $dab->enter();
203
204 } elsif ($cmd eq 'clean') {
205
206 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
207
208 $dab->cleanup (0);
209
210 } elsif ($cmd eq 'dist-clean') {
211
212 die "command '$cmd' expects no arguments.\n" if scalar (@ARGV) != 0;
213
214 $dab->cleanup (1);
215
216 } else {
217 print_usage ("invalid command '$cmd'");
218 exit (-1);
219 }
220
221};
222
223if (my $err = $@) {
224 $dab->logmsg ($@);
225 die ($@);
226}
227
228exit 0;
229
230__END__
231
232=head1 NAME
233
f0134ed2 234dab - Debian LXC Appliance Builder
8ab34b87
DM
235
236=head1 SYNOPSIS
237
238=over
239
240=item B<dab> I<command> I<[OPTIONS]>
241
242=item B<dab init>
243
244Downloads the package descriptions form the
245repository. Also truncates the C<logfile>.
246
247=item B<dab bootstrap>
248
249Bootstrap a debian system and allocate a
250temporary container (we use IDs 90000 and above).
251
252=over
253
254=item I<--exim>
255
256Use exim as MTA (we use postfix by default)
257
258=item I<--minimal>
259
260Do not install standard packages.
261
262=back
263
264=item B<dab veid>
265
266Print used container ID.
267
268=item B<dab basedir>
269
270Print container private directory.
271
272=item B<dab packagefile>
273
274Print the appliance file name.
275
276=item B<dab install I<pkg ...>>
277
278Install one or more packages. I<pkg> can also refer to a file named
279C<xyz.pkglist> which contains a list of packages. All dependencies
280are automatically installed.
281
282=item B<dab unpack I<pkg ...>>
283
284Unpack one or more packages. I<pkg> can also refer to a file named
285C<xyz.pkglist> which contains a list of packages. All dependencies
286are automatically unpacked.
287
288=item B<dab exec I<CMD> I<ARGS>>
289
290Executes command CMD inside the container.
291
292=item B<dab enter>
293
f0134ed2 294Calls C<lxc-attach> - this is for debugging only.
8ab34b87
DM
295
296=item B<dab task mysql>
297
298Install a mysql database server. During appliance generation we use
299C<admin> as mysql root password (also stored in /root/.my.cnf).
300
301=over
302
303=item I<--password=XXX>
304
305Specify the mysql root password. The special value C<random> can be
306use to generate a random root password when the appliance is started
307first time (stored in /root/.my.cnf)
308
309=item I<--start>
310
311Start the mysql server (if you want to execute sql commands during
312appliance generation).
313
314=back
315
316=item B<dab task postgres>
317
318Install a postgres database server.
319
320=over
321
322=item I<--version=XXX>
323
324Select Postgres version. Posible values are C<7.4>, C<8.1> and C<8.3>
325(depends on the selected suite).
326
327=item I<--start>
328
329Start the postgres server (if you want to execute sql commands during
330appliance generation).
331
332=back
333
334=item B<dab task php>
335
336Install php5.
337
338=over
339
340=item I<--memlimit=i>
341
342Set the php I<memory_limit>.
343
344=back
345
346=item B<dab finalize>
347
348Cleanup everything inside the container and generate the final
349appliance package.
350
351=over
352
353=item I<--keepmycnf>
354
355Do not delete file C</root/.my.cfg> (mysql).
356
357=back
358
359=item B<dab list>
360
361List installed packages.
362
363=over
364
365=item I<--verbose>
366
367Also print package versions.
368
369=back
370
371=item B<dab clean>
372
f0134ed2 373Remove all temporary files and destroy the container.
8ab34b87
DM
374
375=item B<dab dist-clean>
376
377Like clean, but also removes the package cache (except when you
378specified your own cache directory in the config file)
379
380=back
381
8ab34b87
DM
382=head1 DESCRIPTION
383
f0134ed2
DM
384dab is a script to automate the creation of LXC appliances. It is
385basically a rewrite of debootstrap in perl, but uses LXC instead of
386chroot and generates LXC templates. Another difference is that it
8ab34b87
DM
387supports multi-stage building of templates. That way you can execute
388arbitrary scripts between to accomplish what you want.
389
390Furthermore some common tasks are fully automated, like setting up a
391database server (mysql or postgres).
392
393To accomplish minimal template creation time, packages are cached to a
394local directory, so you do not need a local debian mirror (although
395this would speed up the first run).
396
397See http://pve.proxmox.com/wiki/Debian_Appliance_Builder for examples.
398
399This script need to be run as root, so it is not recommended to start
f0134ed2
DM
400it on a production machine with running containers. So many people run
401Proxmox VE inside a KVM or VMWare 64bit virtual machine to build
402appliances.
8ab34b87
DM
403
404All generated templates includes an appliance description file. Those
405can be used to build appliance repositories.
406
407=head1 CONFIGURATION
408
409Configuration is read from the file C<dab.conf> inside the current working
410directory. The files contains key value pairs, separated by colon.
411
412=over 2
413
3a9c8648 414=item B<Suite:> I<squeeze|wheezy|jessie|trusty|vivid>
8ab34b87
DM
415
416The Debian or Ubuntu suite.
417
418=item B<Source:> I<URL [components]>
419
420Defines a source location. By default we use the following for debian:
421
422 Source: http://ftp.debian.org/debian SUITE main contrib
423 Source: http://security.debian.org SUITE/updates main contrib
424
425Note: SUITE is a variable and will be substituted.
426
427There are also reasonable defaults for Ubuntu. If you do not specify
428any source the defaults are used.
429
430=item B<Depends:> I<dependencies>
431
432Debian like package dependencies. This can be used to make sure that
433speific package versions are available.
434
435=item B<CacheDir>: I<path>
436
437Allows you to specify the directory where downloaded packages are
438cached.
439
440=item B<Mirror:> I<SRCURL> => I<DSTURL>
441
442Define a mirror location. for example:
443
444 Mirror: http://ftp.debian.org/debian => ftp://mirror/debian
445
446=back
447
448All other settings in this files are also included into the appliance
449description file.
450
451=over 2
452
453=item B<Name:> I<name>
454
455The name of the appliance.
456
457Appliance names must consist only of lower case letters (a-z), digits
458(0-9), plus (+) and minus (-) signs, and periods (.). They must be at
459least two characters long and must start with an alphanumeric
460character.
461
462=item B<Architecture:> I<i386|amd64>
463
464Target architecture.
465
466=item B<Version:> I<upstream_version[-build_revision]>
467
468The version number of an appliance.
469
470=item: B<Section:> I<section>
471
472This field specifies an application area into which the appliance has
473been classified. Currently we use the following section names: system,
474admin, www
475
476=item B<Maintainer:> I<name <email>>
477
478The appliance maintainer's name and email address. The name should
479come first, then the email address inside angle brackets <> (in RFC822
480format).
481
482=item B<Infopage:> I<URL>
483
484Link to web page containing more informations about this appliance.
485
486=item B<Description:> I<single line synopsis>
487
488 extended description over several lines (indended by space) may follow.
489
490=back
491
492=head1 Appliance description file
493
494All generated templates includes an appliance description file called
495
496 /etc/appliance.info
497
498this is the first file inside the tar archive. That way it can be
499easily exctracted without scanning the whole archive. The file itself
500contains informations like a debian C<control> file. It can be used to
501build appliance repositories.
502
503Most fields are directly copied from the configuration file C<dab.conf>.
504
505Additionally there are some auto-generated files:
506
507=over
508
509=item B<Installed-Size:> I<bytes>
510
511It gives the total amount of disk space required to install the named
512appliance. The disk space is represented in megabytes as a simple
513decimal number.
514
515=item B<Type:> I<type>
516
f0134ed2 517This is always C<lxc>.
8ab34b87
DM
518
519=item B<OS:> I<[debian-4.0|debian-5.0|ubuntu-8.0]>
520
521Operation system.
522
523=back
524
525Appliance repositories usually add additional fields:
526
527=over
528
529=item B<md5sum:> I<md5sum>
530
531MD5 checksum
532
533=back
534
535=head1 FILES
536
537The following files are created inside your working directory:
538
539 dab.conf appliance configuration file
540
541 logfile contains installation logs
542
543 .veid stores the used container ID
544
545 cache/* default package cache directory
546
547 info/* package information cache
548
549=head1 AUTHOR
550
551Dietmar Maurer <dietmar@proxmox.com>
552
553Many thanks to Proxmox Server Solutions (www.proxmox.com) for sponsoring
554this work.
555
556=head1 COPYRIGHT AND DISCLAIMER
557
eb58232e 558Copyright (C) 2007-2012 Proxmox Server Solutions GmbH
8ab34b87
DM
559
560Copyright: dab is under GNU GPL, the GNU General Public License.
561
562This program is free software; you can redistribute it and/or modify
563it under the terms of the GNU General Public License as published by
564the Free Software Foundation; version 2 dated June, 1991.
565
566This program is distributed in the hope that it will be useful,
567but WITHOUT ANY WARRANTY; without even the implied warranty of
568MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
569GNU General Public License for more details.
570
571You should have received a copy of the GNU General Public License
572along with this program; if not, write to the
573Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
574MA 02110-1301, USA.