#!/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; use ProjectBuilder::VE; # 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 or a referenced content. 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-type [-d device]][-b boot-method][-m os-ver-arch] [-s script][-a pkg1[,pkg2,...]] [target-dir] pbmkbm [--verbose][--help][--man][--quiet][--type boot-type [--device device]] [--machine os-ver-arch][--boot boot-method] [--script script][--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<-t|--type boot-type> Type of the boot device to generate. A boot-type can be: =over 4 =item B Generate an ISO9660 image format (suitable to be burned later on or loopback mounted. Uses isolinux. =item B Generate a USB image format (typically a key of external hard drive). Uses syslinux. =item B Generate a PXE environement (suitable to be integrated in a PXElinux configuration). Uses pxelinux. =back =item B<-d|--device device-file> Name of the device or file on which you want to create the boot media. =item B<-b|--boot boot-method> This is the boot method to use to create the boot media. A boot-method can be: =over 4 =item B Use the tools of the native distribution to create the boot media. No other dependency. =item B Use the project-builder.org virtual environment notion to create the boot media. No other dependency outside of the project. =item B Use the busybox tool to create the boot media. Cf: L =item B Use the dracut tool to create the boot media. Cf: L =back =item B<-s|--script script> Name of the script you want to execute on the related boot media at the end o the build. =item B<-a|--add pkg1[,pkg2,...]> Additional packages to add from the distribution you want to install on the related boot media at the end of the build. =item B<-m|--machine os-ver-arch> This is the target tuple operating system-version-architecture for which you want to create the boot media. =back =head1 ARGUMENTS target-dir is the directory under which the boot media will be build. =over 4 =back =head1 EXAMPLE To setup a USB busybox based 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 -b busybox To setup an ISO image under /tmp for a RHEL 6 x86_64 distribution issue using the native environment: pbmkbm -t iso -d /tmp -m rhel-6-x86_64 -b ve =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" => \$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'}, "device|d=s" => \$opts{'d'}, "type|t=s" => \$opts{'t'}, "boot|b=s" => \$opts{'b'}, "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'}; # # Initialize distribution info from pb conf file # my $pbos = pb_distro_get_context($ENV{'PBV'}); pb_log(0,"Starting boot media build for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\n"); pb_env_init_pbrc(); # to get content of HOME/.pbrc # # Check target dir # Create if not existent and use default if none given # my $targetdir = shift @ARGV; # # Check for command requirements # my ($req,$opt) = pb_conf_get_if("mkbmcmd","mkbmcmdopt"); pb_check_requirements($req,$opt,$appname); # After that we will need root access die "$appname needs to be run as root" if ($EFFECTIVE_USER_ID != 0); # # Where is our build target directory # if (not defined $targetdir) { $targetdir = "/var/cache/pbmkbm"; my ($vestdpath) = pb_conf_get("mkbmpath"); $targetdir = "$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}" if (defined $vestdpath->{'default'}); } die pb_log(0,"No target-dir specified and no default mkbmpath found in $ENV{'PBETC'}\n") if (not defined $targetdir); # Point to the right subdir and create it if needed pb_mkdir_p($targetdir) if (! -d $targetdir); # Now the preparation is over, we need to do something useful :-) # But it all depends on how we're asked to do it. # # First we need to copy into the target dir all the relevant content pb_mkbm_create_content(); # Then we need to package this content in the destination format pb_mkbm_create_media(); sub pb_mkbm_create_content { pb_log(1,"Creating boot media content\n"); # If not defined use VE mode by default $opts{'b'} = "ve" if (not defined $opts{'b'}); if ($opts{'b'} eq "ve") { # Use existing tools to create a good VE ! pb_ve_launch($ENV{'PBV'},1); } elsif ($opts{'b'} eq "native") { # Use native tools to create a good VE ! } else { die "Unknown method $opts{'b'} used to create the media content"; } # Once the environment is made, add what is needed for this boot media to it. } sub pb_mkbm_create_media { } # Get the package list to download, store them in a cache directory # #my ($mkbmcachedir) = pb_conf_get_if("mkbmcachedir"); #my ($pkgs) = pb_distro_get_param($pbos,pb_conf_get("mkbmmindep")); # # /proc needed # #pb_system("mount -o bind /proc $targetdir/proc","Mounting /proc"); # Installed additional packages we were asked to #if (defined $opts{'a'}) { #$opts{'a'} =~ s/,/ /g; #pb_system("chroot $targetdir /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 $targetdir/proc","Unmounting /proc"); # Executes post-install step if asked for #if ($opts{'s'}) { #pb_system("$opts{'s'} $targetdir","Executing the post-install script: $opts{'s'} $targetdir"); #}