summaryrefslogblamecommitdiffstats
path: root/src/lib/OpenSLX/DistroUtils/Base.pm
blob: f9e6b13b54bc6b1d13d28fc91ae61ade0ae6d714 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                                         











                                                                               



                                   

                    
 

             

















                                             
                  







                                     
                    

                                      
                                                            
     

                                              

     






























                                                  



















                                                                              
                          



                         

                                                             
    























                                                                            

                                        











                                                                            

                                        










                                                                    

                                             







                                                                                

                                        








                                                                                  

                                        











                                                                   

                                        










                                                                

                                        



                  




























                                                       

         
    




































































                                                                                                  
    





                                               
                                                



                                                                        
     



                                                                             
     



























                                                                                    
     











                                                                             
                            
        
     

            
                          

                                      



                   





















                                                                           
                                                                               









                                                         
 
  
# Copyright (c) 2008, 2009 - OpenSLX GmbH
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# -----------------------------------------------------------------------------
# DistroUtils.pm
#    - provides base for distro based utils for OpenSLX
# -----------------------------------------------------------------------------
package OpenSLX::DistroUtils::Base;

use Data::Dumper;
use OpenSLX::Utils;
use Clone qw(clone);
use Switch;

use strict;
use warnings;

sub new
{
    my $class = shift;
    my $self = {};
    return bless $self, $class;
}

sub dumpInit
{
    my $self = shift;
    my $initFile = shift;
    
    print  Dumper($initFile->{'configHash'});
    
    print $self->generateInitFile($initFile);
}

sub _concatContent
{
    my $self = shift;
    my $block = shift;
    
    my $output;
    
    $output = "#";
    $output .= $block->{'blockDesc'};
    $output .= "\n";
    
    my $content = $block->{'content'};
    while ( my ($priority, $contentArray) = each %$content )
    {
        $output .= join("\n", @$contentArray);
        $output .= "\n";
    }
    
    return $output;
}

sub _renderInfoBlock
{
    my $self = shift;
    my $config = shift;
    
    my $tpl = unshiftHereDoc(<<'    End-of-Here');
    ### BEGIN INIT INFO
    # Provides:             %s
    # Required-Start:       %s
    # Required-Stop:        %s
    # Default-Start:        %s
    # Default-Stop:         %s
    # Short-Description:    %s
    ### END INIT INFO
    
    End-of-Here
    
    return sprintf(
      $tpl,
      $config->{'name'},
      $config->{'requiredStart'},
      $config->{'requiredStop'},
      $config->{'defaultStart'},
      $config->{'defaultStop'},
      $config->{'shortDesc'}
    );
}

sub _insertSystemHelperFunctions
{
    my $self = shift;
    my $content = shift;
    
    # do some regex
    
    # ubuntu:
    # log_end_msg
    # log_progress_msg
    # log_daemon_msg
    # log_action_msg
    
    # start-stop-daemon
    
    # suse http://de.opensuse.org/Paketbau/SUSE-Paketkonventionen/Init-Skripte
    
    return $content;
}

sub _renderHighlevelConfig
{
    my $self = shift;
    my $initFile = shift;
    
    my $element;
    my $hlc = $initFile->{'configHash'}->{'highlevelConfig'};
    
    while ( $element = shift(@$hlc)){
        switch ($element->{type}) {
            case 'daemon' {
                my $tpl;
                $tpl  = "%s_BIN=%s \n";
                $tpl .= "[ -x %s_BIN ] || exit 5\n\n";
                $tpl .= "%s_OPTS=\"%s\" \n";
                $tpl .= "[ -f /etc/sysconfig/%s ] . /etc/sysconfig/%s \n\n";
                $tpl .= "[ -f /etc/default/%s ] . /etc/default/%s \n\n";
                $tpl .= "%s_PIDFILE=\"/var/run/%s.init.pid\" \n\n";
                $initFile->addToBlock('head',
                    sprintf(
                        $tpl,
                        uc($element->{shortname}),
                        $element->{binary},
                        uc($element->{shortname}),
                        uc($element->{shortname}),
                        $element->{parameters},
                        $element->{shortname},
                        $element->{shortname},
                        $element->{shortname},
                        $element->{shortname},
                        uc($element->{shortname}),
                        $element->{shortname}
                    ),
                    $element->{priority}
                );
                
                $tpl  = "echo -n \"Starting %s \"\n";
                $tpl .= "startproc -f -p \$%s_PIDFILE \$%s_BIN \$%s_OPTS\n";
                $tpl .= "rc_status -v";
                $initFile->addToCase('start',
                    sprintf(
                        $tpl,
                        $element->{desc},
                        uc($element->{shortname}),
                        uc($element->{shortname}),
                        uc($element->{shortname})
                    ),
                    $element->{priority}
                );

                $tpl  = "echo -n \"Shutting down %s\" \n";
                $tpl .= "killproc -p \$%s_PIDFILE -TERM \$%s_BIN\n";
                $tpl .= "rc_status -v";
                $initFile->addToCase('stop',
                    sprintf(
                        $tpl,
                        $element->{desc},
                        uc($element->{shortname}),
                        uc($element->{shortname})
                    ),
                    10 - $element->{priority}
                );
                
                $tpl  = "## Stop the service and if this succeeds (i.e. the \n";
                $tpl .= "## service was running before), start it again.\n";
                $tpl .= "\$0 status >/dev/null &&  \$0 restart\n\n";
                $tpl .= "# Remember status and be quiet\n";
                $tpl .= "rc_status";
                $initFile->addToCase('try-restart',
                    $tpl,
                    $element->{priority}
                );

                $tpl  = "## Stop the service and regardless of whether it was \n";
                $tpl .= "## running or not, start it again.\n";
                $tpl .= "\$0 stop\n";
                $tpl .= "\$0 start\n\n";
                $tpl .= "# Remember status and be quiet\n";
                $tpl .= "rc_status";
                $initFile->addToCase('restart',
                    $tpl,
                    $element->{priority}
                );
                
                $tpl  = "echo -n \"Reload service %s\"\n";
                $tpl .= "killproc -p \$%s_PIDFILE -HUP \$%s_BIN\n";
                $tpl .= "rc_status -v";
                $initFile->addToCase('reload',
                    sprintf(
                        $tpl,
                        $element->{desc},
                        uc($element->{shortname}),
                        uc($element->{shortname}),
                        uc($element->{shortname})
                    ),
                    $element->{priority}
                );

                $tpl  = "echo -n \"Checking for service %s\"\n";
                $tpl .= "checkproc -p \$%s_PIDFILE \$%s_BIN\n";
                $tpl .= "rc_status -v";
                $initFile->addToCase('status',
                    sprintf(
                        $tpl,
                        $element->{desc},
                        uc($element->{shortname}),
                        uc($element->{shortname})
                    ),
                    $element->{priority}
                );

                
            }
            case 'function' {
                my $tpl;
                $tpl  = "%s () { \n";
                $tpl .= "%s";
                $tpl .= "\n}\n";
                $initFile->addToBlock('functions',
                    sprintf(
                        $tpl,
                        $element->{name},
                        $element->{script}
                    )
                );
                    
            }
            case 'functionCall' {
                my $tpl;
                $tpl  = "%s %s\n";
                #$tpl .= "%s\n ";
                $initFile->addToCase($element->{block},
                    sprintf(
                        $tpl,
                        $element->{function},
                        $element->{parameters},
                        ""
                    ),
                    $element->{priority}
                );
                    
            }
        }
    }
    
}


sub _getInitsystemIncludes
{
    return "\n";
}

sub _renderCasePrefix
{
    return "\n";
}

sub _renderFooter
{
    return "exit 0\n";
}

sub _generateUsage
{
	my $self = shift;
	my $usage = shift;
	my $tpl;
	
    $tpl  = "## print out usage \n";
    $tpl .= "echo \"Usage: \$0 {%s}\" >&2 \n";
    $tpl .= "exit 1";
	
	return sprintf(
	   $tpl,
	   $usage
	);
}

sub _getAuthorBlock
{
	my $tpl;
	
	$tpl  = "# Copyright (c) 2009 - OpenSLX GmbH \n";
    $tpl .= "# \n";
    $tpl .= "# This program is free software distributed under the GPL version 2. \n";
    $tpl .= "# See http://openslx.org/COPYING \n";
    $tpl .= "# \n";
    $tpl .= "# If you have any feedback please consult http://openslx.org/feedback and \n";
    $tpl .= "# send your suggestions, praise, or complaints to feedback\@openslx.org \n";
    $tpl .= "# \n";
    $tpl .= "# General information about OpenSLX can be found at http://openslx.org/ \n";
    $tpl .= "# -----------------------------------------------------------------------------\n";
    $tpl .= "# §filename§ \n";
    $tpl .= "#    - §desc§ \n";
    $tpl .= "# §generated§ \n";
    $tpl .= "# -----------------------------------------------------------------------------\n\n";
	
	return sprintf(
	   $tpl
	);
}

sub generateInitFile
{
    my $self = shift;
    my $initFile = shift;
    my $content;
    my @usage;
    
    # get a copy of initFile object before modifying it..
    my $initFileCopy = clone($initFile);

    $self->_renderHighlevelConfig($initFileCopy);
    
    my $config = $initFileCopy->{'configHash'};
    my $output;
    
    # head
    $output = "#!/bin/sh\n";
    $output .= $self->_getAuthorBlock();
    $output .= $self->_renderInfoBlock($config);
    $output .= $self->_getInitsystemIncludes();
    
    if (keys(%{$config->{'blocks'}->{'head'}->{'content'}}) > 0) {
        $output .= $self->_concatContent($config->{'blocks'}->{'head'});
    }
    
    # functions
    if (keys(%{$config->{'blocks'}->{'functions'}->{'content'}}) > 0) {
        $output .= $self->_concatContent($config->{'blocks'}->{'functions'});
    }
    
    # case block
    $output .= $self->_renderCasePrefix();
    $output .= "\ncase \"\$1\" in \n";  
    
    # get caseBlocks in defined order
    my @blocks = sort{
    	   $config->{'caseBlocks'}->{$a}->{'order'} <=> 
    	   $config->{'caseBlocks'}->{$b}->{'order'}
        } 
    	keys(%{$config->{'caseBlocks'}});
    
    # case block
    while (@blocks)
    {
    	my $block= shift(@blocks);
	    if (keys(%{$config->{'caseBlocks'}->{$block}->{'content'}}) > 0) {
	    	push(@usage, $block);
	        $output .= "  $block)\n";
	        $content = $self->_concatContent($config->{'caseBlocks'}->{$block});
	        $content =~ s/^/    /mg;
	        $output .= $content;
	        $output .= "  ;;\n";
	    } else {
	    	if ($config->{'caseBlocks'}->{$block}->{'required'}) {
	    		print "required block $block undefined";
	    	}
	    }    	
    }
    
    # autogenerate usage
    if (scalar(grep(/usage/, @usage)) == 0) {
    	$initFileCopy->addToCase(
    	       'usage',
    	       $self->_generateUsage(join(', ',@usage))
    	);

 	    $output .= "  *)\n";
        $content = $self->_concatContent($config->{'caseBlocks'}->{'usage'});
        $content =~ s/^/    /mg;
        $output .= $content;
        $output .= "  ;;\n";
    	
    }
    
    # footer
    $output .= "esac\n\n";
    $output .= $self->_renderFooter();
    
    return $output;
    
}

sub getKernelVersion
{
    my $self = shift;
	my $kernelPath = shift;
	
	
	my $newestKernelFile;
    my $newestKernelFileSortKey = '';
    my $kernelPattern = '{vmlinuz,kernel-genkernel-x86}-*';
    foreach my $kernelFile (glob("$kernelPath/$kernelPattern")) {
        next unless $kernelFile =~ m{
            (?:vmlinuz|x86)-(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?-(\d+(?:\.\d+)?)
        }x;
        my $sortKey 
            = sprintf("%02d.%02d.%02d.%02d-%2.1f", $1, $2, $3, $4||0, $5);
        if ($newestKernelFileSortKey lt $sortKey) {
            $newestKernelFile        = $kernelFile;
            $newestKernelFileSortKey = $sortKey;
        }
    }

    if (!defined $newestKernelFile) {
        die; #_tr("unable to pick a kernel-file from path '%s'!", $kernelPath);
    }

    $newestKernelFile =~ /.*?-([.\-0-9]*)-([a-zA-Z]*?)$/;
    my $kernel = {};
    $kernel->{'version'} = $1;
    $kernel->{'suffix'} = $2;
    return $kernel;
	
}


1;