# 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;