]> git.proxmox.com Git - dab.git/blob - dab
bump version to 1.2-1 and fix copyright
[dab.git] / dab
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Getopt::Long;
5 use PVE::DAB;
6
7 $ENV{'LC_ALL'} = 'C';
8
9 sub 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
19 if (scalar (@ARGV) == 0) {
20 print_usage ();
21 exit (-1);
22 }
23
24 my $cmdline = join (' ', @ARGV);
25
26 my $cmd = shift @ARGV;
27
28 if (!$cmd) {
29 print_usage("no command specified");
30 exit (-1);
31 }
32
33 my $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
41 eval {
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
223 if (my $err = $@) {
224 $dab->logmsg ($@);
225 die ($@);
226 }
227
228 exit 0;
229
230 __END__
231
232 =head1 NAME
233
234 dab - 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
244 Downloads the package descriptions form the
245 repository. Also truncates the C<logfile>.
246
247 =item B<dab bootstrap>
248
249 Bootstrap a debian system and allocate a
250 temporary container (we use IDs 90000 and above).
251
252 =over
253
254 =item I<--exim>
255
256 Use exim as MTA (we use postfix by default)
257
258 =item I<--minimal>
259
260 Do not install standard packages.
261
262 =back
263
264 =item B<dab veid>
265
266 Print used container ID.
267
268 =item B<dab basedir>
269
270 Print container private directory.
271
272 =item B<dab packagefile>
273
274 Print the appliance file name.
275
276 =item B<dab install I<pkg ...>>
277
278 Install one or more packages. I<pkg> can also refer to a file named
279 C<xyz.pkglist> which contains a list of packages. All dependencies
280 are automatically installed.
281
282 =item B<dab unpack I<pkg ...>>
283
284 Unpack one or more packages. I<pkg> can also refer to a file named
285 C<xyz.pkglist> which contains a list of packages. All dependencies
286 are automatically unpacked.
287
288 =item B<dab exec I<CMD> I<ARGS>>
289
290 Executes command CMD inside the container.
291
292 =item B<dab enter>
293
294 Calls C<vzctl enter CTID> - this is for debugging only.
295
296 =item B<dab task mysql>
297
298 Install a mysql database server. During appliance generation we use
299 C<admin> as mysql root password (also stored in /root/.my.cnf).
300
301 =over
302
303 =item I<--password=XXX>
304
305 Specify the mysql root password. The special value C<random> can be
306 use to generate a random root password when the appliance is started
307 first time (stored in /root/.my.cnf)
308
309 =item I<--start>
310
311 Start the mysql server (if you want to execute sql commands during
312 appliance generation).
313
314 =back
315
316 =item B<dab task postgres>
317
318 Install a postgres database server.
319
320 =over
321
322 =item I<--version=XXX>
323
324 Select 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
329 Start the postgres server (if you want to execute sql commands during
330 appliance generation).
331
332 =back
333
334 =item B<dab task php>
335
336 Install php5.
337
338 =over
339
340 =item I<--memlimit=i>
341
342 Set the php I<memory_limit>.
343
344 =back
345
346 =item B<dab finalize>
347
348 Cleanup everything inside the container and generate the final
349 appliance package.
350
351 =over
352
353 =item I<--keepmycnf>
354
355 Do not delete file C</root/.my.cfg> (mysql).
356
357 =back
358
359 =item B<dab list>
360
361 List installed packages.
362
363 =over
364
365 =item I<--verbose>
366
367 Also print package versions.
368
369 =back
370
371 =item B<dab clean>
372
373 Remove all temporary file and destroy the used OpenVZ container.
374
375 =item B<dab dist-clean>
376
377 Like clean, but also removes the package cache (except when you
378 specified your own cache directory in the config file)
379
380 =back
381
382 =head1 DESCRIPTION
383
384 dab is a script to automate the creation of OpenVZ appliances. It is
385 basically a rewrite of debootstrap in perl, but uses OpenVZ instead of
386 chroot and generates OpenVZ templates. Another difference is that it
387 supports multi-stage building of templates. That way you can execute
388 arbitrary scripts between to accomplish what you want.
389
390 Furthermore some common tasks are fully automated, like setting up a
391 database server (mysql or postgres).
392
393 To accomplish minimal template creation time, packages are cached to a
394 local directory, so you do not need a local debian mirror (although
395 this would speed up the first run).
396
397 See http://pve.proxmox.com/wiki/Debian_Appliance_Builder for examples.
398
399 This script need to be run as root, so it is not recommended to start
400 it on a production machine with running container. Proxmox VE
401 (http://pve.proxmox.com) is the preferred environment, because it is
402 able to log the console output when a container starts. You wont be
403 able to detect errors during container startup when running on
404 standard OpenVZ. So many people run Proxmox VE inside a KVM or VMWare
405 64bit virtual machine to build appliances.
406
407 All generated templates includes an appliance description file. Those
408 can be used to build appliance repositories.
409
410 =head1 CONFIGURATION
411
412 Configuration is read from the file C<dab.conf> inside the current working
413 directory. 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
419 The Debian or Ubuntu suite.
420
421 =item B<Source:> I<URL [components]>
422
423 Defines 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
428 Note: SUITE is a variable and will be substituted.
429
430 There are also reasonable defaults for Ubuntu. If you do not specify
431 any source the defaults are used.
432
433 =item B<Depends:> I<dependencies>
434
435 Debian like package dependencies. This can be used to make sure that
436 speific package versions are available.
437
438 =item B<CacheDir>: I<path>
439
440 Allows you to specify the directory where downloaded packages are
441 cached.
442
443 =item B<Mirror:> I<SRCURL> => I<DSTURL>
444
445 Define a mirror location. for example:
446
447 Mirror: http://ftp.debian.org/debian => ftp://mirror/debian
448
449 =back
450
451 All other settings in this files are also included into the appliance
452 description file.
453
454 =over 2
455
456 =item B<Name:> I<name>
457
458 The name of the appliance.
459
460 Appliance names must consist only of lower case letters (a-z), digits
461 (0-9), plus (+) and minus (-) signs, and periods (.). They must be at
462 least two characters long and must start with an alphanumeric
463 character.
464
465 =item B<Architecture:> I<i386|amd64>
466
467 Target architecture.
468
469 =item B<Version:> I<upstream_version[-build_revision]>
470
471 The version number of an appliance.
472
473 =item: B<Section:> I<section>
474
475 This field specifies an application area into which the appliance has
476 been classified. Currently we use the following section names: system,
477 admin, www
478
479 =item B<Maintainer:> I<name <email>>
480
481 The appliance maintainer's name and email address. The name should
482 come first, then the email address inside angle brackets <> (in RFC822
483 format).
484
485 =item B<Infopage:> I<URL>
486
487 Link 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
497 All generated templates includes an appliance description file called
498
499 /etc/appliance.info
500
501 this is the first file inside the tar archive. That way it can be
502 easily exctracted without scanning the whole archive. The file itself
503 contains informations like a debian C<control> file. It can be used to
504 build appliance repositories.
505
506 Most fields are directly copied from the configuration file C<dab.conf>.
507
508 Additionally there are some auto-generated files:
509
510 =over
511
512 =item B<Installed-Size:> I<bytes>
513
514 It gives the total amount of disk space required to install the named
515 appliance. The disk space is represented in megabytes as a simple
516 decimal number.
517
518 =item B<Type:> I<type>
519
520 This is always C<openvz>.
521
522 =item B<OS:> I<[debian-4.0|debian-5.0|ubuntu-8.0]>
523
524 Operation system.
525
526 =back
527
528 Appliance repositories usually add additional fields:
529
530 =over
531
532 =item B<md5sum:> I<md5sum>
533
534 MD5 checksum
535
536 =back
537
538 =head1 FILES
539
540 The 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
554 Dietmar Maurer <dietmar@proxmox.com>
555
556 Many thanks to Proxmox Server Solutions (www.proxmox.com) for sponsoring
557 this work.
558
559 =head1 COPYRIGHT AND DISCLAIMER
560
561 Copyright (C) 2007-2012 Proxmox Server Solutions GmbH
562
563 Copyright: dab is under GNU GPL, the GNU General Public License.
564
565 This program is free software; you can redistribute it and/or modify
566 it under the terms of the GNU General Public License as published by
567 the Free Software Foundation; version 2 dated June, 1991.
568
569 This program is distributed in the hope that it will be useful,
570 but WITHOUT ANY WARRANTY; without even the implied warranty of
571 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
572 GNU General Public License for more details.
573
574 You should have received a copy of the GNU General Public License
575 along with this program; if not, write to the
576 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
577 MA 02110-1301, USA.