]> git.proxmox.com Git - dab.git/blame - dab
bump version to 1.2-1 and fix copyright
[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
87 print $dab->vz_priv_dir() . "\n";
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
234dab - Debian OpenVZ Appliance Builder
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
294Calls C<vzctl enter CTID> - this is for debugging only.
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
373Remove all temporary file and destroy the used OpenVZ container.
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
384dab is a script to automate the creation of OpenVZ appliances. It is
385basically a rewrite of debootstrap in perl, but uses OpenVZ instead of
386chroot and generates OpenVZ templates. Another difference is that it
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
400it on a production machine with running container. Proxmox VE
401(http://pve.proxmox.com) is the preferred environment, because it is
402able to log the console output when a container starts. You wont be
403able to detect errors during container startup when running on
404standard OpenVZ. So many people run Proxmox VE inside a KVM or VMWare
40564bit virtual machine to build appliances.
406
407All generated templates includes an appliance description file. Those
408can be used to build appliance repositories.
409
410=head1 CONFIGURATION
411
412Configuration is read from the file C<dab.conf> inside the current working
413directory. The files contains key value pairs, separated by colon.
414
415=over 2
416
417=item B<Suite:> I<etch|lenny|squeeze|hardy|intrepid|jaunty>
418
419The Debian or Ubuntu suite.
420
421=item B<Source:> I<URL [components]>
422
423Defines a source location. By default we use the following for debian:
424
425 Source: http://ftp.debian.org/debian SUITE main contrib
426 Source: http://security.debian.org SUITE/updates main contrib
427
428Note: SUITE is a variable and will be substituted.
429
430There are also reasonable defaults for Ubuntu. If you do not specify
431any source the defaults are used.
432
433=item B<Depends:> I<dependencies>
434
435Debian like package dependencies. This can be used to make sure that
436speific package versions are available.
437
438=item B<CacheDir>: I<path>
439
440Allows you to specify the directory where downloaded packages are
441cached.
442
443=item B<Mirror:> I<SRCURL> => I<DSTURL>
444
445Define a mirror location. for example:
446
447 Mirror: http://ftp.debian.org/debian => ftp://mirror/debian
448
449=back
450
451All other settings in this files are also included into the appliance
452description file.
453
454=over 2
455
456=item B<Name:> I<name>
457
458The name of the appliance.
459
460Appliance names must consist only of lower case letters (a-z), digits
461(0-9), plus (+) and minus (-) signs, and periods (.). They must be at
462least two characters long and must start with an alphanumeric
463character.
464
465=item B<Architecture:> I<i386|amd64>
466
467Target architecture.
468
469=item B<Version:> I<upstream_version[-build_revision]>
470
471The version number of an appliance.
472
473=item: B<Section:> I<section>
474
475This field specifies an application area into which the appliance has
476been classified. Currently we use the following section names: system,
477admin, www
478
479=item B<Maintainer:> I<name <email>>
480
481The appliance maintainer's name and email address. The name should
482come first, then the email address inside angle brackets <> (in RFC822
483format).
484
485=item B<Infopage:> I<URL>
486
487Link to web page containing more informations about this appliance.
488
489=item B<Description:> I<single line synopsis>
490
491 extended description over several lines (indended by space) may follow.
492
493=back
494
495=head1 Appliance description file
496
497All generated templates includes an appliance description file called
498
499 /etc/appliance.info
500
501this is the first file inside the tar archive. That way it can be
502easily exctracted without scanning the whole archive. The file itself
503contains informations like a debian C<control> file. It can be used to
504build appliance repositories.
505
506Most fields are directly copied from the configuration file C<dab.conf>.
507
508Additionally there are some auto-generated files:
509
510=over
511
512=item B<Installed-Size:> I<bytes>
513
514It gives the total amount of disk space required to install the named
515appliance. The disk space is represented in megabytes as a simple
516decimal number.
517
518=item B<Type:> I<type>
519
520This is always C<openvz>.
521
522=item B<OS:> I<[debian-4.0|debian-5.0|ubuntu-8.0]>
523
524Operation system.
525
526=back
527
528Appliance repositories usually add additional fields:
529
530=over
531
532=item B<md5sum:> I<md5sum>
533
534MD5 checksum
535
536=back
537
538=head1 FILES
539
540The following files are created inside your working directory:
541
542 dab.conf appliance configuration file
543
544 logfile contains installation logs
545
546 .veid stores the used container ID
547
548 cache/* default package cache directory
549
550 info/* package information cache
551
552=head1 AUTHOR
553
554Dietmar Maurer <dietmar@proxmox.com>
555
556Many thanks to Proxmox Server Solutions (www.proxmox.com) for sponsoring
557this work.
558
559=head1 COPYRIGHT AND DISCLAIMER
560
eb58232e 561Copyright (C) 2007-2012 Proxmox Server Solutions GmbH
8ab34b87
DM
562
563Copyright: dab is under GNU GPL, the GNU General Public License.
564
565This program is free software; you can redistribute it and/or modify
566it under the terms of the GNU General Public License as published by
567the Free Software Foundation; version 2 dated June, 1991.
568
569This program is distributed in the hope that it will be useful,
570but WITHOUT ANY WARRANTY; without even the implied warranty of
571MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
572GNU General Public License for more details.
573
574You should have received a copy of the GNU General Public License
575along with this program; if not, write to the
576Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
577MA 02110-1301, USA.