#!/usr/bin/perl -w # # pbmkbm, a project-builder.org utility to make boot media # # $Id$ # # Copyright B. Cornec 2011 # Provided under the GPL v2 # Syntax: see at end use strict 'vars'; use Getopt::Long qw(:config auto_abbrev no_ignore_case); use Data::Dumper; use English; use File::Basename; use File::Copy; use ProjectBuilder::Version; use ProjectBuilder::Base; use ProjectBuilder::Env; use ProjectBuilder::Conf; use ProjectBuilder::Distribution; # Global variables my %opts; # CLI Options =pod =head1 NAME pbmkbm - a project-builder.org utility to make boot media =head1 DESCRIPTION pbmkbm creates a bootable media (CD/DVD, USB device, Network, tape, ...) with a minimal distribution in it, suited for building packages for example. It aims at supporting all distributions supported by project-builder.org (RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...) It is inspired by work done by Jean-Marc André around the HP SSSTK and aim at replacing the mindi project (http://www.mondorescue.org), but fully integrated with project-builder.org pbmkbm works in different phases. The first one is to check all pbmkbm needs to gather a certain number of components that could come from various sources and could be put on a different target media. We need a kernel, an initrd/initramfs for additional modules and init script, a root filesystem and a boot configuration file. Kernel, modules could come either from the local installed system (typically for disaster recovery context) or from a kernel package of a given configuration. Utilities could come from busybox, local utilities or set of packages. The root filesystem is made with them. The initrd/initramfs could be made internaly or by calling dracut. THe boot config file is generated from analysis content or provided externally. =head1 SYNOPSIS pbmkbm [-vhq][-t boot-media-type [-d device]][-m os-ver-arch] [-s script][-a pkg1[,pkg2,...]] [target-dir] pbmkbm [--verbose][--help][--man][--quiet][--type boot-media-type [-device device]] [--script script][--iso iso][--add pkg1,[pkg2,...]][target-dir] =head1 OPTIONS =over 4 =item B<-v|--verbose> Print a brief help message and exits. =item B<-h|--help> Print a brief help message and exits. =item B<--man> Prints the manual page and exits. =item B<-q|--quiet> Do not print any output. =item B<-s|--script script> Name of the script you want to execute on the related VEs after the installation. It is executed in host environment. You can use the chroot command to execute actions in the VE. =item B<-a|--add pkg1[,pkg2,...]> Additional packages to add from the distribution you want to install on the related VE at the end of the chroot build. =back =head1 ARGUMENTS =over 4 =item B This is the target directory under which the VE will be created. Created on the fly if needed. If none is given use the default directory hosting VE for project-builder.org (Cf: vepath parameter in $HOME/.pbrc) =back =head1 EXAMPLE To setup a USB boot media on the /dev/sdb device for a Fedora 12 distribution with an i386 architecture issue: pbmkbm -t usb -d /dev/sdb -m fedora-12-i386 =head1 WEB SITES The main Web site of the project is available at L. Bug reports should be filled using the trac instance of the project at L. =head1 USER MAILING LIST Cf: L for announces and L for the development of the pb project. =head1 CONFIGURATION FILE Uses Project-Builder.org configuration file (/etc/pb/pb.conf or /usr/local/etc/pb/pb.conf) =head1 AUTHORS The Project-Builder.org team L lead by Bruno Cornec L. =head1 COPYRIGHT Project-Builder.org is distributed under the GPL v2.0 license described in the file C included with the distribution. =cut # --------------------------------------------------------------------------- my ($projectbuilderver,$projectbuilderrev) = pb_version_init(); my $appname = "pbmkbm"; $ENV{'PBPROJ'} = $appname; # Initialize the syntax string pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n"); pb_temp_init(); GetOptions("help|?|h" => \$opts{'h'}, "man|m" => \$opts{'man'}, "verbose|v+" => \$opts{'v'}, "quiet|q" => \$opts{'q'}, "log-files|l=s" => \$opts{'l'}, "script|s=s" => \$opts{'s'}, "machine|m=s" => \$opts{'m'}, "add|a=s" => \$opts{'a'}, "version|V=s" => \$opts{'V'}, ) || pb_syntax(-1,0); if (defined $opts{'h'}) { pb_syntax(0,1); } if (defined $opts{'man'}) { pb_syntax(0,2); } if (defined $opts{'v'}) { $pbdebug = $opts{'v'}; } if (defined $opts{'q'}) { $pbdebug=-1; } if (defined $opts{'l'}) { open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!"; $pbLOG = \*pbLOG; $pbdebug = 0 if ($pbdebug == -1); } pb_log_init($pbdebug, $pbLOG); # Get VE name $ENV{'PBV'} = $opts{'m'}; die pb_syntax(-1,1) if (not defined $ENV{'PBV'}); die "Needs to be run as root" if ($EFFECTIVE_USER_ID != 0); # # Initialize distribution info from pb conf file # pb_log(0,"Starting VE build for $ENV{'PBV'}\n"); my $pbos = pb_distro_get_context($ENV{'PBV'}); # # Check target dir # Create if not existent and use default if none given # pb_env_init_pbrc(); # to get content of HOME/.pbrc my $vepath = shift @ARGV; # # Check for command requirements # my ($req,$opt) = pb_conf_get_if("mkbmcmd","mkbmcmdopt"); pb_check_requirements($req,$opt,$appname); if (not defined $vepath) { my ($vestdpath) = pb_conf_get("vepath"); $vepath = "$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}" if (defined $vestdpath->{'default'}); } die pb_log(0,"No target-dir specified and no default vepath found in $ENV{'PBETC'}\n") if (not defined $vepath); pb_mkdir_p($vepath) if (! -d $vepath); # # Get the package list to download, store them in a cache directory # my ($mkbmcachedir) = pb_conf_get_if("mkbmcachedir"); my ($pkgs,$mirror) = pb_distro_get_param($pbos,pb_conf_get("mkbmmindep","mkbmmirrorsrv")); my $cachedir = "/var/cache/pbmkbm"; $cachedir = $mkbmcachedir->{'default'} if (defined $mkbmcachedir->{'default'}); # Point to the right subdir and create it if needed $cachedir .= "/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}"; pb_mkdir_p($cachedir) if (! -d $cachedir); # # /proc needed # pb_system("mount -o bind /proc $vepath/proc","Mounting /proc"); # Installed additional packages we were asked to if (defined $opts{'a'}) { $opts{'a'} =~ s/,/ /g; pb_system("chroot $vepath /bin/bash -c \"$pbos->{'install'} $opts{'a'} \"","Adding packages to OS by running $pbos->{'install'} $opts{'a'}"); } # # Clean up # pb_log(1,"Cleaning up\n"); pb_system("umount $vepath/proc","Unmounting /proc"); # Executes post-install step if asked for if ($opts{'s'}) { pb_system("$opts{'s'} $vepath","Executing the post-install script: $opts{'s'} $vepath"); }