summaryrefslogblamecommitdiffstats
path: root/src/boot-env/OpenSLX/BootEnvironment/PBS.pm
blob: 2072884bd770872646816cfae46a27bf569cbec0 (plain) (tree)





























































































                                                                                           
                                                                                                                 



                                                 
                                                                                                     










                                                                                   
                                                                                                            










                                                                                  
                                                                                                                   


























































































































                                                                                                       
# Copyright (c) 2008 - 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/
# -----------------------------------------------------------------------------
# BootEnvironment::Preboot.pm
#    - provides general preboot implementation of the BootEnvironment API.
# -----------------------------------------------------------------------------
package OpenSLX::BootEnvironment::PBS;

use strict;
use warnings;

use base qw(OpenSLX::BootEnvironment::Base);

use OpenSLX::MakeInitRamFS::Engine::PBS;

use Clone qw(clone);
use File::Basename;
use File::Path;

use Data::Dumper;

use JSON;
use HTTP::Request::Common;
use LWP::UserAgent;

use OpenSLX::Basics;
use OpenSLX::ConfigDB qw(:support);
use OpenSLX::Utils;

sub initialize
{
    my $self   = shift;
    my $params = shift;
    
    return if !$self->SUPER::initialize($params);

    $self->{'original-path'} = "$openslxConfig{'public-path'}/pbs";
    $self->{'target-path'}   = "$openslxConfig{'public-path'}/pbs.new";

    $self->{'requires-default-client-config'} = 0;
        # we do not need a default.tgz since there's always an explicit client

    
    if (!$self->{'dry-run'}) {
        mkpath([$self->{'original-path'}]);
        rmtree($self->{'target-path'});
        mkpath("$self->{'target-path'}/client-config");
    }

    return 1;
}

sub writeBootloaderMenuFor
{
    my $self             = shift;
    my $client           = shift;
    my $externalClientID = shift;
    my $systemInfos      = shift || [];

    my $prebootSystemInfo
        = clone($self->_pickSystemWithNewestKernel($systemInfos));

    vlog(
        0, 
        _tr(
            "\nsend preboot information for client '%s' to pbs (%s)\n".
            "  (image templates provided based of %s) ...", 
            $client->{name}, $client->{attrs}->{preboot_server}, $prebootSystemInfo->{name}
        )
    );

    $self->_createPrebootStuff($client, $prebootSystemInfo);

    my $kernel      = "$self->{'target-path'}/imagebase/vmlinuz";
    my $initramfs   = "$self->{'target-path'}/imagebase/initramfs";
    
    my $kernel_md5 = qx/md5sum $kernel | awk '{print \$1}'/;
    my $initramfs_md5 = qx/md5sum $initramfs | awk '{print \$1}'/;

    my $data_json = to_json({
    	'slxinfo'   => qx/slxversion/,
    	'kernel'    => basename($prebootSystemInfo->{'kernel-file'}),
        'kernel_md5' => trim($kernel_md5), 
        'initramfs_md5' => trim($initramfs_md5), 
    	'systems'   => $systemInfos
    });
    my $ua = LWP::UserAgent->new;
    my $res = $ua->request(POST 'http://pbs.experimental.openslx.org/backend/system/sync', [data => $data_json]);
    
    if ($res->is_success) {
    	my $resData = from_json($res->content);
    	if ($resData->{'getKernel'} eq 'fresh') {
            $res = $ua->request(POST 'http://pbs.experimental.openslx.org/backend/system/addkernel', 
                ['kernel' => basename($prebootSystemInfo->{'kernel-file'}),
                 'kernelFile' => ["$self->{'target-path'}/imagebase/vmlinuz"],
                 'initramfsFile' => ["$self->{'target-path'}/imagebase/initramfs"],
                  ],
                'Content_Type' => 'form-data'
            );
            
            print Dumper($res->content);
    		
    	} else {
            if ($resData->{'getKernel'} eq 'update') {
                $res = $ua->request(POST 'http://pbs.experimental.openslx.org/backend/system/updatekernel', 
                    ['kernel' => basename($prebootSystemInfo->{'kernel-file'}),
                     'kernelFile' => ["$self->{'target-path'}/imagebase/vmlinuz"],
                      ],
                    'Content_Type' => 'form-data'
                );
                
                print Dumper($res->content);
            } else {
                # do nothing
            }
            if ($resData->{'getInitramfs'} eq 'update') {
	            $res = $ua->request(POST 'http://pbs.experimental.openslx.org/backend/system/updateinitramfs', 
	                ['kernel' => basename($prebootSystemInfo->{'kernel-file'}),
	                 'initramfsFile' => ["$self->{'target-path'}/imagebase/initramfs"],
	                  ],
	                'Content_Type' => 'form-data'
	            );
	            
	            print Dumper($res->content);
            } else {
                # do nothing
            }
    	}
    } else {
    	vlog(0, 'communication with pbs failed.. please check and rerun..');
    }

    return 1;
}

sub _createPrebootStuff
{
    my $self   = shift;
    my $client = shift;
    my $info   = shift;
    
    my $prebootClass = instantiateClass(
        "OpenSLX::BootEnvironment::Preboot::Base"
    );
    
    my $imagebase = "$self->{'target-path'}/imagebase";
    
    $prebootClass->initialize($self);
    $client->{attrs}->{boot_uri} = $client->{attrs}->{preboot_server};
    mkpath("$imagebase");
    $self->_makePBSInitRamFS($info, "$imagebase/initramfs", $client);

    my $kernelFile = $info->{'kernel-file'};
    my $kernelName = basename($kernelFile);
    slxsystem(qq{cp -p "$kernelFile" "$imagebase/vmlinuz"})
        unless $self->{'dry-run'};
    
    return 1;
}

sub _pickSystemWithNewestKernel
{
    my $self        = shift;
    my $systemInfos = shift;

    my $systemWithNewestKernel;
    my $newestKernelFileSortKey = '';
    foreach my $system (@$systemInfos) {
        next unless $system->{'kernel-file'} =~ 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) {
            $systemWithNewestKernel  = $system;
            $newestKernelFileSortKey = $sortKey;
        }
    }

    if (!defined $systemWithNewestKernel) {
        die _tr("unable to pick a system to be used for preboot!");
    }
    return $systemWithNewestKernel;
}

sub _makePBSInitRamFS
{
    my $self       = shift;
    my $info       = shift;
    my $initramfs  = shift;
    my $client     = shift;

    my $vendorOS = $info->{'vendor-os'};
    my $kernelFile = basename(followLink($info->{'kernel-file'}));

    my $attrs = clone($info->{attrs} || {});

    my $bootURI = $client->{attrs}->{boot_uri};
    if (!$bootURI) {
        die _tr("client $client->{name} needs an URI in attribute 'boot_uri' to be used for preboot!");
    }

    chomp(my $slxVersion = qx{slxversion});

    my $params = {
        'attrs'          => $attrs,
        'export-name'    => undef,
        'export-uri'     => undef,
        'initramfs'      => $initramfs,
        'kernel-params'  
            => [ split ' ', ($info->{attrs}->{kernel_params} || '') ],
        'kernel-version' => $kernelFile =~ m[-(.+)$] ? $1 : '',
        'plugins'        => '',
        'root-path'
            => "$openslxConfig{'private-path'}/stage1/$vendorOS->{name}",
        'slx-version'    => $slxVersion,
        'system-name'    => $info->{name},
        'preboot-id'     => $client->{name},
        'boot-uri'       => $bootURI,
    };

    # TODO: make debug-level an explicit attribute, it's used in many places!
    my $kernelParams = $info->{attrs}->{kernel_params} || '';
    if ($kernelParams =~ m{debug(?:=(\d+))?}) {
        my $debugLevel = defined $1 ? $1 : '1';
        $params->{'debug-level'} = $debugLevel;
    }

    my $makeInitRamFSEngine 
        = OpenSLX::MakeInitRamFS::Engine::PBS->new($params);
    $makeInitRamFSEngine->execute($self->{'dry-run'});

    # copy back kernel-params, as they might have been changed (by plugins)
    $info->{attrs}->{kernel_params} 
        = join ' ', $makeInitRamFSEngine->kernelParams();

    return;
}

1;