Update of /cvsroot/leaf/src/bering-uclibc4/buildtool
In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv11477

Added Files:
        buildimage.pl 
Log Message:
Initial commit of buildimage.pl

--- NEW FILE: buildimage.pl ---
#!/usr/bin/perl
#
#  Script to create a Bering-uClibc disk image from existing packages
#
#  Copyright (C) 2010 David M Brooke, [email protected]
#  Based on buildpacket.pl by Martin Hejl
#
#  This software is distributed under the GNU General Public Licence,
#  please see the file COPYING
#
#  $Header: /cvsroot/leaf/src/bering-uclibc4/buildtool/buildimage.pl,v 1.1 
2010/09/25 19:52:54 davidmbrooke Exp $
#
use strict;
use warnings;
use Config::General;
use Getopt::Long;
use Date::Format;
use File::Spec;
use File::Temp;
use File::Copy;
use Carp;

my %configHash = ( );
my $label;
my $image;
my $verbose;
my $debug;
my $Usage =
qq{Usage: $0 --image=ImgDir --relver=VersionLabel [--verbose]
   image    Parent directory for buildimage.cfg, under buildtool/image
            e.g. Bering-uClibc-isolinux-std
   relver   String to append to image name to show release version
            e.g. 4.0beta1
   verbose  [Optional] Report progress during execution
};

sub createTempDir( );
sub cleanTempDir( );
sub system_exec( $;$$ );
sub createDirUnlessItExists( $ );
sub copyFilesToTempDir( $$ );
sub copyFilesWithSearchAndReplace( $$@ );


# Process command line arguments
GetOptions( "verbose!" => \$verbose,
            "image=s"  => \$image,
            "relver=s"  => \$label,
            "debug!"   => \$debug ) or die $Usage;

die $Usage unless defined( $image );
die $Usage unless defined( $label );
$configHash{ '{VERSION}' } = $label;

my $baseDir = File::Spec->rel2abs( File::Basename::dirname( $0 ) );

# Fetch the buildtool config
my $btConfig = new Config::General(
    "-ConfigFile" => File::Spec->catfile(
        $baseDir,
        'conf',
        'buildtool.conf' ),
    "-LowerCaseNames" => 1,
    "-ExtendedAccess" => 1 );

# Fetch the global config (e.g. conf/sources.cfg)
my $glConfig = new Config::General(
    "-ConfigFile" => File::Spec->catfile(
        $baseDir,
        $btConfig->value( 'globalconffile' ) ),
    "-LowerCaseNames" => 1,
    "-ExtendedAccess" => 1 );

# Fetch the image specific config
my $imConfig = new Config::General(
    "-ConfigFile" => File::Spec->catfile(
        $baseDir,
        $btConfig->value( 'image_dir' ),
        $image,
        $btConfig->value( 'buildimage_config' ) ),
    "-LowerCaseNames" => 1,
    "-ExtendedAccess" => 1 );

my $sourceDir = File::Spec->canonpath(
    File::Spec->catdir(
        $baseDir,
        $btConfig->value('source_dir') ) );

my $stagingDir = File::Spec->canonpath(
    File::Spec->catdir(
        $baseDir,
        $btConfig->value('staging_dir') ) );

# Generate date label
$configHash{ '{DATE}' } = time2str( "%Y-%m-%d", time );
print "Build Date is:\t\t$configHash{ '{DATE}' }\n" if $verbose;

# Extract kernel version from source tree
my $kver;
open( FH, "<".$sourceDir."/linux/linux/.config" );
while ( <FH> )
{ if ( /version: (.*)/ ) { $kver = $1; last; } }
close( FH );
print "Kernel Version is:\t$kver\n" if $verbose;

# Create directory to hold image contents
my $tmpDir = createTempDir( );

# Always create full modules.tgz
print "Creating modules.tgz...\n" if $verbose;
system_exec( "cd $stagingDir/lib/modules/$kver ; tar -czf $tmpDir/modules.tgz * 
--exclude=build --exclude=source", "Error building modules.tgz" );

## Extract name of image to build from config file
#my @names = keys( %{ $imConfig->value( 'image' ) } );
#if ( scalar @names < 1 || scalar @names > 1 )
#{
    #die "Exactly one Image name required in config file";
#}
#my $imgName = $names[0];

# Extract name and type of image to build from config file
my $imageStruc = $imConfig->value( 'image' );
my $imgName = $imageStruc->{ 'imagename' };
die "ImageName is not specified in config file" unless defined $imgName;
print "Image name:\t\t$imgName\n" if $verbose;
my $imgType = $imageStruc->{ 'imagetype' };
die "ImageType is not specified in config file" unless defined $imgType;
print "Image type:\t\t$imgType\n" if $verbose;

# Extract configuration variables from config file
# Populate global configHash with Search-And-Replace Key:Value
while ( my ( $key, $value ) = each( %{ $imageStruc->{ 'config' } } ) )
{
    my $ucKey = $key;
    $ucKey =~ tr/[a-z]/[A-Z]/;
    $configHash{ $ucKey } = $value;
}

# Process <Contents> block from config file
my $imageContents = $imageStruc->{ 'contents' };

# Should be exactly one <Kernel> block
my $imageKernel = $imageContents->{ 'kernel' };
die "<Kernel> entry not present in config file" unless defined $imageKernel;
copyFilesToTempDir(
    $imageKernel->{ 'source' },
    $imageKernel->{ 'filename' } );
# Capture path to kernel to use in sys/isolinux.cfg
$configHash{ '{KERNEL}' } = "/".$imageKernel->{ 'filename' } ;

# Should be multiple <File> blocks
# Don't even bother coping with the case of a single <File> block
foreach my $fileStruc ( @{ $imageContents->{ 'file' } } )
{
    print "DEBUG - Processing block for <File> ",$fileStruc->{ 'filename' 
},"\n" if $debug;
    # Do we need to Search-And-Replace strings in this file? 
    if ( defined( $fileStruc->{ 'searchandreplace' } ) )
    {
        # Yes; need to Search-And-Replace for this file entry
        # We have an ARRAY if there is >1 SearchAndReplace entry for this file
        if ( ref( $fileStruc->{ 'searchandreplace' } ) eq 'ARRAY' )
        {
            print "DEBUG - Processing multiple S&R strings\n" if $debug;
            my @sAndR = @{ $fileStruc->{ 'searchandreplace' } };
            copyFilesWithSearchAndReplace( 
                $fileStruc->{ 'source' },
                $fileStruc->{ 'filename' },
                @sAndR );
        }
        # We have a SCALAR if there is 1 SearchAndReplace entry for this file
        else
        {
            print "DEBUG - Processing single S&R strings\n" if $debug;
            my @sAndR = ( $fileStruc->{ 'searchandreplace' } );
            copyFilesWithSearchAndReplace( 
                $fileStruc->{ 'source' },
                $fileStruc->{ 'filename' },
                @sAndR );
        }
    }
    else
    {
        # No; no need to Search-And-Replace for this entry - just copy file
        copyFilesToTempDir(
                $fileStruc->{ 'source' },
                $fileStruc->{ 'filename' } );
    }
}

# Complete the processing depending on the image type specified
if ( $imgType eq "syslinux" )
{
    print "Performing SYSLINUX processing...\n" if $verbose;
    my $fileName = File::Spec->catfile(
        $baseDir,
        $btConfig->value( 'image_dir' ),
        $image,
        $imgName."_".$label.".tar.gz" );
    system_exec( "cd $tmpDir ; tar -czf $fileName .", "Error creating image 
tarfile: $!" );
}
elsif ( $imgType eq "isolinux" )
{
    print "Performing ISOLINUX processing...\n" if $verbose;
    my $fileName = File::Spec->catfile(
        $baseDir,
        $btConfig->value( 'image_dir' ),
        $image,
        $imgName."_".$label.".iso" );

    # Summary of mkisofs arguments:
    #  -o               Name of generated image file
    #  -v               Verbose messages
    #  -b               El Torito boot image filename
    #  -no-emul-boot    CD-ROM is not a disk image; do not emulate a disk
    #  -c               Name of boot catalog  file to be generated by mkisofs
    #  -boot-load-size  Number of 512-byte sectors to load in no-emul mode
    #  -boot-info-table Include a table of the image file layout
    #  -l               Allow long (31-character) filenames
    #  -R               Use Rock Ridge extensions
    #  -r               Use standard values for file ownership and permissions
    #  .                Create image of current directory
    system_exec( "cd $tmpDir ; mkisofs -o $fileName -v -b isolinux/isolinux.bin 
-c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -l -R -r 
.", "Error running mkisofs: $!" );

}
else
{
    die "Unsupported image type $imgType\n";
}

# Tidyup
cleanTempDir( );

# End of main


sub createTempDir( )
{
    my $tempDIR;
    eval
    {
        $tempDIR = File::Temp::tempdir(
            'BUILDIMAGE_STAGING_XXXX',
            'TMPDIR' => 1 );
    };
    if ( $@ ne '' )
    {
        confess( "Unable to create temporary directory. $@" );
    }
    print "Temporary directory:\t$tempDIR\n" if $verbose;
    return( $tempDIR );
}

sub cleanTempDir( )
{
    print "Cleaning up dir $tmpDir\n" if $verbose;
    confess( "Temp dir undefined" ) unless defined( $tmpDir );
    confess( "Will not delete root dir" ) if File::Spec->canonpath( $tmpDir ) 
eq File::Spec->rootdir( );
    system( "rm -rf $tmpDir" );
    rmdir( $tmpDir );
}

sub system_exec( $;$$ )
{
    my ( $command, $error_message, $no_cleanup ) = @_;
    $no_cleanup = 0 unless defined( $no_cleanup );
    $error_message = "$command failed " unless defined( $error_message );
    print "Executing $command\n" if $verbose;
    my $retVal = system( $command );
    if ( $retVal>>8 != 0 )
    { 
        cleanTempDir( ) unless $no_cleanup;
        confess( "$error_message $!" );
    }
}

sub createDirUnlessItExists( $ )
{
    my ( $path ) = @_;
    while ( ! ( -e $path ) )
    {
        my @dirs = File::Spec->splitdir( $path );
        my $dirToCreate = "";
        foreach my $dir ( @dirs )
        {
            $dirToCreate = File::Spec->catdir( $dirToCreate, $dir );
            if ( ! ( -e $dirToCreate ) )
            {
                print "Creating directory $dirToCreate\n" if $verbose;
                mkdir( $dirToCreate ) or confess( "creating dir " . $path . " 
failed. $!" );
            }
        }
    }
}

sub copyFilesToTempDir( $$ )
{
    my ( $source, $target ) = @_;
    my $absSource = File::Spec->catdir( $baseDir, $source );
    my $absTarget = File::Spec->catdir( $tmpDir, $target );
    # Check for '*' in Source
    if ( $absSource =~ /\*/ )
    {
        # Source contains '*' so Target _must_ be a directory
        createDirUnlessItExists( $absTarget );
        system_exec( "cp -r $absSource $absTarget", "Failed to copy files: $!" 
);
    }
    else
    {
        # Source does not contain '*' so Target is a file
        # Might still need to create the directory for that file
        my $destDir = File::Basename::dirname( $absTarget );
        createDirUnlessItExists( $destDir );
        system_exec( "cp -r $absSource $absTarget", "Failed to copy files: $!" 
);
    }
}

sub copyFilesWithSearchAndReplace( $$@ )
{
    my ( $source, $target, @sAndR ) = @_;
    my $absSource = File::Spec->catdir( $baseDir, $source );
    my $absTarget = File::Spec->catdir( $tmpDir, $target );
    # Check for '*' in Source
    if ( $absSource =~ /\*/ )
    {
        # Source contains '*' so Target _must_ be a directory
        createDirUnlessItExists( $absTarget );
        die "Copying multiple files with SearchAndReplace is not currently 
supported. Sorry.";
    }
    else
    {
        # Source does not contain '*' so Target is a file
        # Might still need to create the directory for that file
        my $destDir = File::Basename::dirname( $absTarget );
        createDirUnlessItExists( $destDir );
        open( IFH, "<".$absSource ) or confess( "Error: $!" );
        open( OFH, ">".$absTarget ) or confess( "Error: $!" );
        while ( <IFH> )
        {
            foreach my $string ( @sAndR )
            {
                s/$string/$configHash{ $string }/;
            }
            print OFH;
        }
        close( OFH );
        close( IFH );
    }
}


exit;

__END__

=pod

=head1 NAME

buildimage.pl - create a Bering-uClibc disk image

=head1 SYNOPSIS

B<buildimage.pl> --image=ImgDir --relver=VersionLabel [--verbose]

   image    Parent directory for buildimage.cfg, under buildtool/image
            e.g. Bering-uClibc-isolinux-std
   relver   String to append to image name to show release version
            e.g. 4.0beta1
   verbose  [Optional] Report progress during execution

=head1 DESCRIPTION

B<buildimage.pl> creates a Bering-uClibc disk image based on parameter
settings defined in a configuration file (buildimage.cfg) located within a
sub-directory of buildtool/image. The name of this sub-directory is specified
with the "--image" command-line argument.

The disk image can be for SYSLINUX (suitable for writing to a flash drive)
or can use ISOLINUX. The choice between these is specified in buildimage.cfg.

For SYSLINUX, the "image" is a .tar.gz file which needs to be extracted
onto suitably prepared media.
For ISOLINUX the "image" is a .iso file which can be burned to a CD-R.

Note that the name of the image file is based on the ImageName field in the
configuration file which may be different from the --image argument.

=head1 SEE ALSO

http://sourceforge.net/apps/mediawiki/leaf/index.php?title=Bering-uClibc_4.x_-_Developer_Guide_-_Building_an_Image

=cut

# vi: set ai sw=4 wm=5 fo=cql:


------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
leaf-cvs-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/leaf-cvs-commits

Reply via email to