From 416ab8a37f1b07dc9f6c0fb3ff1a8ff2036510b5 Mon Sep 17 00:00:00 2001 From: Sebastian Schmelzer Date: Thu, 2 Sep 2010 17:50:49 +0200 Subject: change dir structure --- src/installer/OpenSLX/OSExport/BlockDevice/AoE.pm | 95 + src/installer/OpenSLX/OSExport/BlockDevice/Base.pm | 77 + .../OpenSLX/OSExport/BlockDevice/DNBD2.pm | 91 + src/installer/OpenSLX/OSExport/BlockDevice/LBD.pm | 76 + src/installer/OpenSLX/OSExport/BlockDevice/NBD.pm | 87 + src/installer/OpenSLX/OSExport/Distro/Any.pm | 66 + src/installer/OpenSLX/OSExport/Distro/Base.pm | 71 + src/installer/OpenSLX/OSExport/Distro/Debian.pm | 60 + src/installer/OpenSLX/OSExport/Distro/Fedora.pm | 65 + src/installer/OpenSLX/OSExport/Distro/Gentoo.pm | 59 + src/installer/OpenSLX/OSExport/Distro/SciLin.pm | 94 + src/installer/OpenSLX/OSExport/Distro/Suse.pm | 145 ++ src/installer/OpenSLX/OSExport/Distro/Ubuntu.pm | 108 ++ src/installer/OpenSLX/OSExport/Engine.pm | 364 ++++ src/installer/OpenSLX/OSExport/FileSystem/Base.pm | 148 ++ src/installer/OpenSLX/OSExport/FileSystem/NFS.pm | 238 +++ .../OpenSLX/OSExport/FileSystem/SquashFS.pm | 410 +++++ src/installer/OpenSLX/OSSetup/Distro/Any_Clone.pm | 31 + src/installer/OpenSLX/OSSetup/Distro/Base.pm | 371 ++++ src/installer/OpenSLX/OSSetup/Distro/Debian.pm | 135 ++ src/installer/OpenSLX/OSSetup/Distro/Debian_3_1.pm | 74 + src/installer/OpenSLX/OSSetup/Distro/Fedora.pm | 48 + src/installer/OpenSLX/OSSetup/Distro/Gentoo.pm | 33 + src/installer/OpenSLX/OSSetup/Distro/Scilin.pm | 48 + src/installer/OpenSLX/OSSetup/Distro/Suse.pm | 98 + src/installer/OpenSLX/OSSetup/Distro/Ubuntu.pm | 119 ++ src/installer/OpenSLX/OSSetup/Engine.pm | 1929 ++++++++++++++++++++ src/installer/OpenSLX/OSSetup/MetaPackager/Base.pm | 98 + src/installer/OpenSLX/OSSetup/MetaPackager/apt.pm | 142 ++ .../OpenSLX/OSSetup/MetaPackager/smart.pm | 127 ++ src/installer/OpenSLX/OSSetup/MetaPackager/yum.pm | 117 ++ .../OpenSLX/OSSetup/MetaPackager/zypper.pm | 122 ++ src/installer/OpenSLX/OSSetup/Packager/Base.pm | 98 + src/installer/OpenSLX/OSSetup/Packager/dpkg.pm | 102 ++ src/installer/OpenSLX/OSSetup/Packager/rpm.pm | 89 + src/installer/slxos-export | 323 ++++ src/installer/slxos-setup | 402 ++++ 37 files changed, 6760 insertions(+) create mode 100644 src/installer/OpenSLX/OSExport/BlockDevice/AoE.pm create mode 100644 src/installer/OpenSLX/OSExport/BlockDevice/Base.pm create mode 100644 src/installer/OpenSLX/OSExport/BlockDevice/DNBD2.pm create mode 100644 src/installer/OpenSLX/OSExport/BlockDevice/LBD.pm create mode 100644 src/installer/OpenSLX/OSExport/BlockDevice/NBD.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Any.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Base.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Debian.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Fedora.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Gentoo.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/SciLin.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Suse.pm create mode 100644 src/installer/OpenSLX/OSExport/Distro/Ubuntu.pm create mode 100644 src/installer/OpenSLX/OSExport/Engine.pm create mode 100644 src/installer/OpenSLX/OSExport/FileSystem/Base.pm create mode 100644 src/installer/OpenSLX/OSExport/FileSystem/NFS.pm create mode 100644 src/installer/OpenSLX/OSExport/FileSystem/SquashFS.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Any_Clone.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Base.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Debian.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Debian_3_1.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Fedora.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Gentoo.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Scilin.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Suse.pm create mode 100644 src/installer/OpenSLX/OSSetup/Distro/Ubuntu.pm create mode 100644 src/installer/OpenSLX/OSSetup/Engine.pm create mode 100644 src/installer/OpenSLX/OSSetup/MetaPackager/Base.pm create mode 100644 src/installer/OpenSLX/OSSetup/MetaPackager/apt.pm create mode 100644 src/installer/OpenSLX/OSSetup/MetaPackager/smart.pm create mode 100644 src/installer/OpenSLX/OSSetup/MetaPackager/yum.pm create mode 100644 src/installer/OpenSLX/OSSetup/MetaPackager/zypper.pm create mode 100644 src/installer/OpenSLX/OSSetup/Packager/Base.pm create mode 100644 src/installer/OpenSLX/OSSetup/Packager/dpkg.pm create mode 100644 src/installer/OpenSLX/OSSetup/Packager/rpm.pm create mode 100755 src/installer/slxos-export create mode 100755 src/installer/slxos-setup (limited to 'src/installer') diff --git a/src/installer/OpenSLX/OSExport/BlockDevice/AoE.pm b/src/installer/OpenSLX/OSExport/BlockDevice/AoE.pm new file mode 100644 index 00000000..cc7866b5 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/BlockDevice/AoE.pm @@ -0,0 +1,95 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# AoE.pm +# - provides ATA-over-Ethernet specific overrides of the +# OpenSLX::OSExport::BlockDevice API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::BlockDevice::AoE; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::BlockDevice::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::OSExport::BlockDevice::Base 1; +use OpenSLX::Utils; + +# +# +# N.B.: currently this is just a stub +# +# + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {'name' => 'aoe',}; + return bless $self, $class; +} + +sub getExportPort +{ + my $self = shift; + my $openslxDB = shift; + + return $openslxDB->incrementGlobalCounter('next-nbd-server-port'); +} + +sub generateExportURI +{ + my $self = shift; + my $export = shift; + + my $serverIP = $export->{server_ip} || ''; + my $server + = length($serverIP) ? $serverIP : generatePlaceholderFor('serverip'); + $server .= ":$export->{port}" if length($export->{port}); + + return "aoe://$server"; +} + +sub requiredBlockDeviceModules +{ + my $self = shift; + + return qw( aoe ); +} + +sub requiredBlockDeviceTools +{ + my $self = shift; + + # TODO: is there any such tool? + + return; +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + print(('#' x 80) . "\n"); + print _tr( + "Please make sure you start a corresponding aoe-server:\n\t%s\n", + "... (don't know how this is done yet)" + ); + print(('#' x 80) . "\n"); + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/BlockDevice/Base.pm b/src/installer/OpenSLX/OSExport/BlockDevice/Base.pm new file mode 100644 index 00000000..6469c2f4 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/BlockDevice/Base.pm @@ -0,0 +1,77 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# Base.pm +# - provides empty base of the OpenSLX OSExport::BlockDevice API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::BlockDevice::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSExport::BlockDevice::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + my $fs = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between block-device and its engine + + $self->{'fs'} = $fs; + weaken($self->{'fs'}); + # avoid circular reference between block-device and its file-system +} + +sub getExportPort +{ +} + +sub generateExportURI +{ +} + +sub requiredBlockDeviceModules +{ +} + +sub requiredBlockDeviceTools +{ +} + +sub showExportConfigInfo +{ +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSExport::BlockDevice::Base - the base class for all OSExport::BlockDevices + +=cut diff --git a/src/installer/OpenSLX/OSExport/BlockDevice/DNBD2.pm b/src/installer/OpenSLX/OSExport/BlockDevice/DNBD2.pm new file mode 100644 index 00000000..25e112ee --- /dev/null +++ b/src/installer/OpenSLX/OSExport/BlockDevice/DNBD2.pm @@ -0,0 +1,91 @@ +# Copyright (c) 2006, 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/ +# ----------------------------------------------------------------------------- +# DNBD2.pm +# - provides DNBD2+Squashfs-specific overrides of the +# OpenSLX::OSExport::BlockDevice API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::BlockDevice::DNBD2; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::BlockDevice::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::OSExport::BlockDevice::Base 1; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {'name' => 'dnbd2',}; + return bless $self, $class; +} + +sub getExportPort +{ + my $self = shift; + my $openslxDB = shift; + + return $openslxDB->incrementGlobalCounter('next-nbd-server-port'); +} + +sub generateExportURI +{ + my $self = shift; + my $export = shift; + + my $serverIP = $export->{server_ip} || ''; + my $server + = length($serverIP) ? $serverIP : generatePlaceholderFor('serverip'); + $server .= ":$export->{port}" if length($export->{port}); + + return "dnbd2://$server"; +} + +sub requiredBlockDeviceModules +{ + my $self = shift; + + return qw( dnbd2 ); +} + +sub requiredBlockDeviceTools +{ + my $self = shift; + + return qw( ); +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + print '#' x 80 , "\n", + _tr( + "Please make sure you start a corresponding dnbd2-server:\n\t%s\n", + "dnbd2-server /etc/dnbd2/server.conf\n" + ), + "Create or modify a config file like /etc/dnbd2/server.conf, looking like:", + "\n# dnbd2 server configuration\n\n", + "$export->{port}\n", + "$self->{fs}->{'export-path'}\n\n", + '#' x 80, "\n"; + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/BlockDevice/LBD.pm b/src/installer/OpenSLX/OSExport/BlockDevice/LBD.pm new file mode 100644 index 00000000..e8df1b04 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/BlockDevice/LBD.pm @@ -0,0 +1,76 @@ +# Copyright (c) 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/ +# ----------------------------------------------------------------------------- +# LBD.pm +# - provides the local block devices with Squashfs container specific +# overrides of the OpenSLX::OSExport::BlockDevice API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::BlockDevice::LBD; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::BlockDevice::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::OSExport::BlockDevice::Base 1; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {'name' => 'LBD',}; + return bless $self, $class; +} + +sub generateExportURI +{ + my $self = shift; + + return "lbd://sda1/squashfs"; +} + +sub requiredBlockDeviceModules +{ + my $self = shift; + + return qw( ehci_hcd usb_storage scsi_mod sd_mod loop ext3 ); +} + +sub requiredBlockDeviceTools +{ + my $self = shift; + + return qw( ); +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + print '#' x 80 , "\n", + _tr( + "Please make sure you copy all corresponding files to your boot\n", + "device you wish to deploy (e.g. bootable USB stick)\n" + ), + "Make your device bootable using syslinux for (v)fat or extlinux for\n", + "ext2/3 partitions. Cat HPA syslinux' mbr to the device very beginning\n", + "and set the boot flag to the partion you made bootable\n\n", + '#' x 80, "\n"; + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/BlockDevice/NBD.pm b/src/installer/OpenSLX/OSExport/BlockDevice/NBD.pm new file mode 100644 index 00000000..58378751 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/BlockDevice/NBD.pm @@ -0,0 +1,87 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# NBD.pm +# - provides NBD+Squashfs-specific overrides of the +# OpenSLX::OSExport::BlockDevice API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::BlockDevice::NBD; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::BlockDevice::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::OSExport::BlockDevice::Base 1; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {'name' => 'nbd',}; + return bless $self, $class; +} + +sub getExportPort +{ + my $self = shift; + my $openslxDB = shift; + + return $openslxDB->incrementGlobalCounter('next-nbd-server-port'); +} + +sub generateExportURI +{ + my $self = shift; + my $export = shift; + + my $serverIP = $export->{server_ip} || ''; + my $server + = length($serverIP) ? $serverIP : generatePlaceholderFor('serverip'); + $server .= ":$export->{port}" if length($export->{port}); + + return "nbd://$server"; +} + +sub requiredBlockDeviceModules +{ + my $self = shift; + + return qw( nbd ); +} + +sub requiredBlockDeviceTools +{ + my $self = shift; + + return qw( nbd-client ); +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + print(('#' x 80) . "\n"); + print _tr( + "Please make sure you start a corresponding nbd-server:\n\t%s\n", + "nbd-server $export->{port} $self->{fs}->{'export-path'} -r" + ); + print(('#' x 80) . "\n"); + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/Distro/Any.pm b/src/installer/OpenSLX/OSExport/Distro/Any.pm new file mode 100644 index 00000000..dc3c7c8b --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Any.pm @@ -0,0 +1,66 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Any.pm +# - provides generic overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Any; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'any', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + + /var + - /var/tmp/* + - /var/spool/* + - /var/run/* + - /var/lock/* + - /var/log/* + - /var/lib/xdm + - /var/lib/smart + - /var/cache/yum + - /var/cache/man/* + - /usr/share/vmware/* + - /tmp/* + - /sys/* + - /proc/* + - /mnt/* + - /media/* + + /lib/modules/*/misc/vmblock.o + + /lib/modules/*/misc/vmnet.o + + /lib/modules/*/misc/vmmon.o + - /lib/klibc/events/* + - /boot/initrd* + - /boot/grub + "; + return; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSExport/Distro/Base.pm b/src/installer/OpenSLX/OSExport/Distro/Base.pm new file mode 100644 index 00000000..5223ce95 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Base.pm @@ -0,0 +1,71 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Base.pm +# - provides base implementation of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSExport::Distro::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between distro and its engine + + $self->initDistroInfo(); + return; +} + +sub initDistroInfo +{ +} + +sub getSquashfsVersion +{ + my $self = shift; + my $distroVersion = shift; + + return "4.0"; +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSExport::Distro::Base + +=head1 SYNOPSIS + +... + +=cut diff --git a/src/installer/OpenSLX/OSExport/Distro/Debian.pm b/src/installer/OpenSLX/OSExport/Distro/Debian.pm new file mode 100644 index 00000000..98e9b42f --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Debian.pm @@ -0,0 +1,60 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Debian.pm +# - provides Debian-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Debian; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'debian', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + - /var/log/* + - /var/lib/xdm + - /var/cache/man/* + - /var/cache/apt/archives/* + - /usr/share/vmware/* + - /tmp/* + - /sys/* + - /proc/* + - /mnt/* + - /media/* + - /lib/klibc/events/* + - /boot/initrd* + - /boot/grub + "; + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/Distro/Fedora.pm b/src/installer/OpenSLX/OSExport/Distro/Fedora.pm new file mode 100644 index 00000000..4c196bd1 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Fedora.pm @@ -0,0 +1,65 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Fedora.pm +# - provides Fedora-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Fedora; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'fedora', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + # TODO: check and refine this! + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + - /var/lock/* + - /var/log/* + - /var/lib/xdm + - /var/lib/smart + - /var/cache/yum + - /var/cache/man/* + - /usr/share/vmware/* + - /tmp/* + - /sys/* + - /proc/* + - /mnt/* + - /media/* + - /lib/klibc/events/* + - /boot/initrd* + - /boot/grub + - *.rpmsave + - *.rpmnew + "; + return; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSExport/Distro/Gentoo.pm b/src/installer/OpenSLX/OSExport/Distro/Gentoo.pm new file mode 100644 index 00000000..79fa2210 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Gentoo.pm @@ -0,0 +1,59 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Gentoo.pm +# - provides Gentoo-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Gentoo; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'gentoo', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + - /var/log/* + - /var/lib/xdm + - /var/lib/init.d/* + - /var/cache/man/* + - /usr/share/vmware/* + - /tmp/* + - /sys/* + - /proc/* + - /mnt/* + - /media/* + - /boot/initrd* + - /boot/grub + "; + return; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSExport/Distro/SciLin.pm b/src/installer/OpenSLX/OSExport/Distro/SciLin.pm new file mode 100644 index 00000000..272b5cef --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/SciLin.pm @@ -0,0 +1,94 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/SciLin.pm +# - provides SciLin-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::SciLin; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'scilin', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + - /var/mail + - /var/log/* + - /var/lock/* + - /var/lib/xdm + - /var/lib/vm* + - /var/lib/suspend* + - /var/lib/smart + - /var/lib/gdm/* + - /var/lib/dhcp* + - /var/lib/bluetooth/ + - /var/cache/yum + - /var/cache/man/* + - /var/cache/zypp/* + + /usr/lib/python*/*/*.o + + /usr/lib/perl5/*/*/*/*.o + + /usr/lib/gcc/*/*/*.o + + /usr/lib/*.o + + /usr/X11R6/lib/modules/drivers/*.o + + /usr/X11R6/lib/modules/drivers/linux/*.o + - /usr/bin/BackGround + - /tmp/* + - /sys/* + - /proc/* + - /opt/kde3/share/apps/kdm/read_sysconfig.sh + - /opt/kde3/share/autostart/runupdater.desktop + - /opt/kde3/share/autostart/profile_chooser-autostart.desktop + - /opt/kde3/share/autostart/kinternet.desktop + - /usr/share/gnome/autostart/gpk-update-icon*.desktop + - /mnt/* + - /media/* + + /media + + /lib/modules/*/misc/vmblock.o + + /lib/modules/*/misc/vmnet.o + + /lib/modules/*/misc/vmmon.o + - /etc/*rpmnew + - /etc/*rpmorig + - /etc/*pptp* + - /etc/*ppp* + - /etc/dhcp* + - /etc/cron.*/* + - /etc/netplug* + - /etc/sysconfig/network* + - /etc/X11/xkb + - /boot/initrd* + - /boot/grub + - *.rpmsave + - *.rpmnew + "; + return; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/Distro/Suse.pm b/src/installer/OpenSLX/OSExport/Distro/Suse.pm new file mode 100644 index 00000000..9e62e6e5 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Suse.pm @@ -0,0 +1,145 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Suse.pm +# - provides SUSE-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Suse; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'suse', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + + /var/run/screen + - /var/mail + - /var/log/* + - /var/lock/* + - /var/lib/zypp/* + - /var/lib/zmd + - /var/lib/xdm + - /var/lib/vm* + - /var/lib/suspend* + - /var/lib/smart + - /var/lib/sax + - /var/lib/hardware/* + - /var/lib/gdm/* + - /var/lib/dhcp* + - /var/lib/bluetooth/ + - /var/lib/YaST2/you/mnt/* + - /var/lib/YaST2/backup_boot_sectors + - /var/cache/sax + - /var/cache/libx11/compose/* + - /var/cache/beagle + - /var/cache/yum + - /var/cache/man/* + - /var/cache/zypp/* + - /var/adm/backup/rpmdb/* + - /var/adm/mount/AP* + - /var/adm/SuSEconfig + - /usr/share/vmware/* + - /usr/lib/zen-updater + + /usr/lib/python*/*/*.o + + /usr/lib/perl5/*/*/*/*.o + + /usr/lib/gcc/*/*/*.o + + /usr/lib/*.o + + /usr/X11R6/lib/modules/drivers/*.o + + /usr/X11R6/lib/modules/drivers/linux/*.o + - /usr/bin/zen-* + - /usr/bin/nw-manager + - /usr/X11R6/bin/BackGround + - /usr/bin/BackGround + - /usr/share/autostart/SUSEgreeter.desktop + - /tmp/* + - /sys/* + - /proc/* + - /opt/kde3/share/apps/kdm/read_sysconfig.sh + - */autostart/suseplugger.desktop + - */autostart/susewatcher.desktop + - */autostart/runupdater.desktop + - */autostart/profile_chooser-autostart.desktop + - */autostart/opensuseupdater.desktop + - */autostart/knetworkmanager-autostart.desktop + - */autostart/kerry.autostart.desktop + - */autostart/kinternet.desktop + - */autostart/SUSEgreeter.desktop + - */autostart/zen-updater-auto.desktop + - */autostart/beagle*.desktop + - */autostart/gpk-update-icon*.desktop + - */autostart/kupdateapplet.desktop + - */config/SuSE/default/kupdateapplet.* + - */config/SuSE/default/*.live + - */config/SuSE/default/*beagle* + - /mnt/* + - /media/* + + /media + + /lib/modules/*/misc/vmblock.o + + /lib/modules/*/misc/vmnet.o + + /lib/modules/*/misc/vmmon.o + - /etc/*rpmnew + - /etc/*rpmorig + - /etc/*YaST2save + - /etc/*pptp* + - /etc/*ppp* + - /etc/dhcp* + - /etc/cron.*/* + - /etc/sysconfig/network/ifcfg-* + - /etc/X11/xdm/SuSEconfig.xdm + - /boot/initrd* + - /boot/grub + - *.rpmsave + - *.rpmnew + - *.YaST2save + "; + return; +} + + +sub getSquashfsVersion +{ + my $self = shift; + my $distroVersion = shift; + + my %versionMap = ( + '11.0' => '3.2', + '11.1' => '3.2', + '11.2' => '3.3', + '11.3' => '4.0' + ); + + my $distroDefault = '4.0'; + + return $versionMap{$distroVersion} || $distroDefault; +} + + +1; diff --git a/src/installer/OpenSLX/OSExport/Distro/Ubuntu.pm b/src/installer/OpenSLX/OSExport/Distro/Ubuntu.pm new file mode 100644 index 00000000..3826f019 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Distro/Ubuntu.pm @@ -0,0 +1,108 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSExport/Distro/Ubuntu.pm +# - provides Ubuntu-specific overrides of the OSExport Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Distro::Ubuntu; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'ubuntu', + }; + return bless $self, $class; +} + +sub initDistroInfo +{ + my $self = shift; + + $self->{'export-filter'} = " + - /var/tmp/* + - /var/spool/* + - /var/run/* + + /var/run/screen + - /var/log/* + - /var/log/apt/* + + /var/log/apt + - /var/lib/*dm/* + - /var/lib/libnss-ldap/* + - /var/cache/apt/archives/* + + /var/cache/apt/archives/partial + - /var/cache/man/* + - /var/cache/nscd/* + - /usr/share/vmware/* + - /usr/share/autostart/trackerd.desktop + - /usr/share/autostart/knetworkmanager.desktop + - /etc/update-motd.d/90* + - /etc/update-motd.d/91* + - /etc/update-motd.d/98* + - /tmp/* + - /sys/* + - /proc/* + - /mnt/* + - /media/* + - /lib/udev/devices + - /initrd* + - /etc/cron.*/* + - /boot/initrd* + - /boot/grub + - /etc/xdg/compiz + - /etc/xdg/autostart/adept_notifier_auto.desktop + - /etc/xdg/autostart/evolution*alarm*notify* + - /etc/xdg/autostart/knetworkmanager* + - /etc/xdg/autostart/nm-applet.desktop + - /etc/xdg/autostart/system-config-printer-applet-kde.desktop + - /etc/xdg/autostart/tracker* + - /etc/xdg/autostart/jockey-* + - /etc/xdg/autostart/ica* + - /etc/xdg/autostart/hplip* + - /etc/xdg/autostart/redhat* + - /etc/xdg/autostart/gnome-power-manager* + - /etc/xdg/autostart/update* + - /etc/xdg/update-notifier.desktop + - /etc/xdg/user-dirs-update-gtk.desktop + "; + return; +} + + +sub getSquashfsVersion +{ + my $self = shift; + my $distroVersion = shift; + + my %versionMap = ( + '8.04' => '3.3', + '8.10' => '3.3', + '9.04' => '3.3', + '9.10' => '4.0', + '10.04' => '4.0' + ); + + my $distroDefault = '4.0'; + + return $versionMap{$distroVersion} || $distroDefault; +} + + +1; diff --git a/src/installer/OpenSLX/OSExport/Engine.pm b/src/installer/OpenSLX/OSExport/Engine.pm new file mode 100644 index 00000000..251869e0 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/Engine.pm @@ -0,0 +1,364 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# Engine.pm +# - provides driver engine for the OSExport API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::Engine; + +use strict; +use warnings; + +our (@ISA, @EXPORT, $VERSION); +$VERSION = 1.01; # API-version . implementation-version + +use Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw( + %supportedExportFileSystems %supportedExportBlockDevices + @supportedExportTypes +); + +use File::Basename; + +use OpenSLX::Basics; +use OpenSLX::Utils; + +our ( + %supportedExportFileSystems, %supportedExportBlockDevices, + @supportedExportTypes, +); + +%supportedExportFileSystems = ( + 'nfs' => 'NFS', + 'sqfs' => 'SquashFS', +); + +%supportedExportBlockDevices = ( + 'dnbd2' => 'DNBD2', + 'nbd' => 'NBD', + 'aoe' => 'AoE', +); + +@supportedExportTypes = ( + 'nfs', + 'sqfs-aoe', + 'sqfs-dnbd2', + 'sqfs-nbd', +); + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + + my $self = {}; + + return bless $self, $class; +} + +sub initializeFromExisting +{ + my $self = shift; + my $exportName = shift; + + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + my $export = $openslxDB->fetchExportByFilter({'name' => $exportName}); + if (!defined $export) { + die _tr("Export '%s' not found in DB, giving up!", $exportName); + } + my $vendorOS = + $openslxDB->fetchVendorOSByFilter({'id' => $export->{vendor_os_id}}); + + $openslxDB->disconnect(); + + $self->_initialize($vendorOS->{name}, $vendorOS->{id}, $export->{name}, + $export->{type}); + return; +} + +sub initializeForNew +{ + my $self = shift; + my $vendorOSName = shift; + my $exportType = lc(shift); + + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + my $vendorOS = $openslxDB->fetchVendorOSByFilter({'name' => $vendorOSName}); + if (!defined $vendorOS) { + die _tr("vendor-OS '%s' not found in DB, giving up!", $vendorOSName); + } + + my $exportName = "${vendorOSName}::${exportType}"; + + $openslxDB->disconnect(); + + $self->_initialize($vendorOS->{name}, $vendorOS->{id}, $exportName, + $exportType); + return; +} + +sub exportVendorOS +{ + my $self = shift; + + vlog( + 1, + _tr( + "vendor-OS from '%s' will be exported to '%s'", + $self->{'vendor-os-path'}, + $self->{'exporter'}->{'export-path'} + ) + ); + if (!$self->{'exporter'}->checkRequirements($self->{'vendor-os-path'})) { + die _tr( + "clients wouldn't be able to access the exported root-fs!\nplease " + . "install the missing module(s) or use another export-type."); + } + + $self->{'exporter'}->exportVendorOS($self->{'vendor-os-path'},); + vlog( + 0, + _tr( + "vendor-OS '%s' successfully exported to '%s'!", + $self->{'vendor-os-path'}, + $self->{exporter}->{'export-path'} + ) + ); + $self->_addExportToConfigDB(); + return; +} + +sub purgeExport +{ + my $self = shift; + + if ($self->{'exporter'}->purgeExport()) { + vlog( + 0, + _tr( + "export '%s' successfully removed!", + $self->{exporter}->{'export-path'} + ) + ); + } + $self->_removeExportFromConfigDB(); + return; +} + +sub generateExportURI +{ + my $self = shift; + + return $self->{exporter}->generateExportURI(@_); +} + +sub requiredFSMods +{ + my $self = shift; + + return $self->{exporter}->requiredFSMods(); +} + +sub requiredFSTools +{ + my $self = shift; + + return $self->{exporter}->requiredFSTools(); +} + +################################################################################ +### implementation methods +################################################################################ +sub _initialize +{ + my $self = shift; + my $vendorOSName = shift; + my $vendorOSId = shift; + my $exportName = shift; + my $exportType = lc(shift); + + if ($vendorOSName eq '<<>>') { + die _tr("you can't do that with the default vendor-OS!\n"); + } + if (!grep { $_ eq $exportType } @supportedExportTypes) { + vlog(0, + _tr("Sorry, export type '%s' is unsupported.\n", $exportType) + . _tr("List of supported export types:\n\t") + . join("\n\t", sort @supportedExportTypes)); + exit 1; + } + $exportType =~ m[^(\w+)(?:-(\w+))?$]; + my $exportFS = lc($1); + my $exportBD = lc($2); + vlog(2, "export-filesys='$exportFS' export-blockdev='$exportBD'"); + + $self->{'vendor-os-name'} = $vendorOSName; + $self->{'vendor-os-id'} = $vendorOSId; + $self->{'export-name'} = $exportName; + $self->{'export-type'} = $exportType; + $vendorOSName =~ m[^(.+?\-[^-]+)]; + $self->{'distro-name'} = lc($1); + my $distroName = ucfirst(lc($1)); + + # load module for the requested distro: + my $distro = loadDistroModule({ + distroName => $distroName, + distroScope => 'OpenSLX::OSExport::Distro', + fallbackName => 'Any', + }); + if (!$distro) { + die _tr( + 'unable to load any OSExport::Distro module for vendor-OS %s!', + $vendorOSName + ); + } + $distro->initialize($self); + $self->{distro} = $distro; + + # load module for the requested export type: + my $fsModuleName = $supportedExportFileSystems{$exportFS}; + my $exporter = + instantiateClass("OpenSLX::OSExport::FileSystem::$fsModuleName"); + if (length($exportBD)) { + my $blockModuleName = $supportedExportBlockDevices{$exportBD}; + my $blockDevice = + instantiateClass("OpenSLX::OSExport::BlockDevice::$blockModuleName"); + $blockDevice->initialize($self, $exporter); + $exporter->initialize($self, $blockDevice); + } else { + $exporter->initialize($self); + } + $self->{'exporter'} = $exporter; + + $self->{'vendor-os-path'} = + "$openslxConfig{'private-path'}/stage1/$vendorOSName"; + + return; +} + +sub _addExportToConfigDB +{ + my $self = shift; + + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + my $export = $openslxDB->fetchExportByFilter( + { + 'name' => $self->{'export-name'}, + 'vendor_os_id' => $self->{'vendor-os-id'}, + } + ); + if (defined $export) { + vlog( + 0, + _tr( + "No need to change export '%s' in OpenSLX-database.\n", + $self->{'export-name'} + ) + ); + $self->{exporter}->showExportConfigInfo($export); + } else { + $export = { + 'vendor_os_id' => $self->{'vendor-os-id'}, + 'name' => $self->{'export-name'}, + 'type' => $self->{'export-type'}, + }; + + my $id = $self->{exporter}->addExportToConfigDB($export, $openslxDB); + vlog( + 0, + _tr( + "Export '%s' has been added to DB (ID=%s)...\n", + $self->{'export-name'}, $id + ) + ); + + $self->{exporter}->showExportConfigInfo($export) if $id; + } + + my $system = $openslxDB->fetchSystemByFilter({ + 'name' => $self->{'export-name'}, + }); + if (!defined $system) { + # now create a default system for that export, using the standard kernel: + system("slxconfig add-system $self->{'export-name'}"); + } + + $openslxDB->disconnect(); + return; +} + +sub _removeExportFromConfigDB +{ + my $self = shift; + + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + # remove export from DB: + my $exportName = $self->{'export-name'}; + my $export = $openslxDB->fetchExportByFilter({'name' => $exportName,}); + if (!defined $export) { + vlog( + 0, + _tr( + "Export '%s' doesn't exist in OpenSLX-database.\n", $exportName + ) + ); + } else { + # remove all systems using this export and then remove the + # export itself: + my @systemIDs = + map { $_->{id} } + $openslxDB->fetchSystemByFilter({'export_id' => $export->{id}}, 'id'); + vlog( + 1, + _tr( + "removing systems '%s' from DB, since they belong to the export" + . " being deleted.\n", + join ',', + @systemIDs + ) + ); + $openslxDB->removeSystem(\@systemIDs); + $openslxDB->removeExport($export->{id}); + vlog(0, _tr("Export '%s' has been removed from DB.\n", $exportName)); + } + + $openslxDB->disconnect(); + return; +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSExport::Engine - + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +... + +=cut + diff --git a/src/installer/OpenSLX/OSExport/FileSystem/Base.pm b/src/installer/OpenSLX/OSExport/FileSystem/Base.pm new file mode 100644 index 00000000..05f3c6a0 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/FileSystem/Base.pm @@ -0,0 +1,148 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# Base.pm +# - provides empty base of the OpenSLX OSExport::FileSystem API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::FileSystem::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use File::Basename; +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSExport::FileSystem::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between file-system and its engine +} + +sub exportVendorOS +{ +} + +sub purgeExport +{ +} + +sub checkRequirements +{ + return 1; +} + +sub addExportToConfigDB +{ + my $self = shift; + my $export = shift; + my $openslxDB = shift; + + return $openslxDB->addExport($export); +} + +sub generateExportURI +{ +} + +sub requiredFSMods +{ +} + +sub requiredFSTools +{ +} + +sub showExportConfigInfo +{ +} + +################################################################################ +### implementation methods +################################################################################ +sub _pickKernelVersion +{ + my $self = shift; + my $vendorOSPath = shift; + + my $kernel = followLink("$vendorOSPath/boot/vmlinuz"); + if (!-e $kernel) { + # 'vmlinuz'-link doesn't exist, so we have to pick the kernel manually + my $osSetupEngine = instantiateClass("OpenSLX::OSSetup::Engine"); + $osSetupEngine->initialize($self->{engine}->{'vendor-os-name'}, 'none'); + $kernel = $osSetupEngine->pickKernelFile("$vendorOSPath/boot"); + } + my $kernelName = basename($kernel); + if ($kernelName !~ m[-(.+)$]) { + die _tr("unable to determine version of kernel '%s'!", $kernelName); + } + return $1; +} + +sub _locateKernelModule +{ + my $self = shift; + my $vendorOSPath = shift; + my $moduleName = shift; + my $defaultPaths = shift; + + vlog(1, _tr("locating kernel-module '%s'", $moduleName)); + # check default paths first: + foreach my $defPath (@$defaultPaths) { + vlog(2, "trying $defPath/$moduleName"); + my $target = followLink("$defPath/$moduleName", $vendorOSPath); + return $target unless !-e $target; + } + # use brute force to search for the newest incarnation of the module: + use File::Find; + my $location; + my $locationAge = 9999999; + vlog(2, "searching in $vendorOSPath/lib/modules"); + find sub { + return unless $_ eq $moduleName; + if (-M _ < $locationAge) { + $locationAge = -M _; + $location = $File::Find::name; + vlog(2, "located at $location (age=$locationAge days)"); + } + }, "$vendorOSPath/lib/modules"; + if (defined $location) { + return followLink($location, $vendorOSPath); + } + return; +} + +1; + +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSExport::FileSystem::Base - the base class for all OSExport::FileSystems + +=cut diff --git a/src/installer/OpenSLX/OSExport/FileSystem/NFS.pm b/src/installer/OpenSLX/OSExport/FileSystem/NFS.pm new file mode 100644 index 00000000..9bd2ca87 --- /dev/null +++ b/src/installer/OpenSLX/OSExport/FileSystem/NFS.pm @@ -0,0 +1,238 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# NFS.pm +# - provides NFS-specific overrides of the OpenSLX::OSExport::FileSystem API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::FileSystem::NFS; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::FileSystem::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'nfs', + }; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + + my $exportBasePath = "$openslxConfig{'public-path'}/export"; + $self->{'export-path'} = "$exportBasePath/nfs/$engine->{'vendor-os-name'}"; + return; +} + +sub exportVendorOS +{ + my $self = shift; + my $source = shift; + + my $target = $self->{'export-path'}; + if ($self->_isTargetBindMounted($source, $target)) { + warn _tr( + "%s is a bind-mount to vendor-OS root - rsync step is skipped!", + $target + ); + return; + } + + $self->_copyViaRsync($source, $target); + + return; +} + +sub purgeExport +{ + my $self = shift; + + my $source = $self->{'engine'}->{'vendor-os-path'}; + my $target = $self->{'export-path'}; + if ($self->_isTargetBindMounted($source, $target)) { + warn _tr( + "%s is a bind-mount to vendor-OS root - removal step is skipped!", + $target + ); + return; + } + + if (system("rm -r $target")) { + vlog(0, _tr("unable to remove export '%s'!", $target)); + return 0; + } + return 1; +} + +sub checkRequirements +{ + my $self = shift; + my $vendorOSPath = shift; + + # determine most appropriate kernel version ... + my $kernelVer = $self->_pickKernelVersion($vendorOSPath); + + # ... and check if that kernel-version provides all the required modules + my $nfsMod = $self->_locateKernelModule( + $vendorOSPath, + 'nfs.ko', + [ + "$vendorOSPath/lib/modules/$kernelVer/kernel/fs/nfs", + "$vendorOSPath/lib/modules/$kernelVer/kernel/fs" + ] + ); + if (!defined $nfsMod) { + warn _tr("unable to find nfs-module for kernel version '%s'.", + $kernelVer); + return; + } + return 1; +} + +sub generateExportURI +{ + my $self = shift; + my $export = shift; + my $vendorOS = shift; + + my $serverIP = $export->{server_ip} || ''; + my $server + = length($serverIP) ? $serverIP : generatePlaceholderFor('serverip'); + my $port = $export->{port} || ''; + $server .= ":$port" if length($port); + + my $exportPath = "$openslxConfig{'public-path'}/export"; + return "nfs://$server$exportPath/nfs/$vendorOS->{name}"; +} + +sub requiredFSMods +{ + my $self = shift; + + return qw( nfs ); +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + print (('#' x 80)."\n"); + print _tr("Please make sure the following line is contained in /etc/exports\nin order to activate the NFS-export of this vendor-OS:\n\t%s\n", + "$self->{'export-path'}\t*(ro,no_root_squash,async,no_subtree_check)"); + print (('#' x 80)."\n"); + +# TODO : add something a bit more clever here... +# my $exports = slurpFile("/etc/exports"); + return; +} + +################################################################################ +### implementation methods +################################################################################ +sub _copyViaRsync +{ + my $self = shift; + my $source = shift; + my $target = shift; + + if (system("mkdir -p $target")) { + die _tr("unable to create directory '%s', giving up! (%s)\n", + $target, $!); + } + my $includeExcludeList = $self->_determineIncludeExcludeList(); + vlog(1, _tr("using include-exclude-filter:\n%s\n", $includeExcludeList)); + my $rsyncFH; + my $additionalRsyncOptions = $ENV{SLX_RSYNC_OPTIONS} || ''; + my $rsyncCmd + = "rsync -av --delete-excluded --exclude-from=- $additionalRsyncOptions" + . " $source/ $target"; + vlog(2, "executing: $rsyncCmd\n"); + open($rsyncFH, '|-', $rsyncCmd) + or die _tr("unable to start rsync for source '%s', giving up! (%s)", + $source, $!); + print $rsyncFH $includeExcludeList; + close($rsyncFH) + or die _tr("unable to export to target '%s', giving up! (%s)", + $target, $!); + return; +} + +sub _determineIncludeExcludeList +{ + my $self = shift; + + # Rsync uses a first match strategy, so we mix the local specifications + # in front of the filterset given by the package (as the local filters + # should always overrule the vendor filters): + my $distroName = $self->{engine}->{'distro-name'}; + my $localFilterFile + = "$openslxConfig{'config-path'}/distro-info/$distroName/export-filter"; + my $includeExcludeList + = slurpFile($localFilterFile, { failIfMissing => 0 }); + $includeExcludeList .= $self->{engine}->{distro}->{'export-filter'}; + $includeExcludeList =~ s[^\s+][]igms; + # remove any leading whitespace, as rsync doesn't like it + return $includeExcludeList; +} + +sub _isTargetBindMounted +{ + my $self = shift; + my $source = shift; + my $target = shift; + + # For development purposes, it is very desirable to be able to take a + # shortcut that avoids doing the actual copying of the folders (as that + # takes a considerable amount of time). + # In order to support this, we explicitly check if the OpenSLX NFS export + # root folder (/srv/openslx/export/nfs) is a bind-mount of the OpenSLX + # stage1 folder (/var/opt/openslx/stage1). + # If that is the case, we print a notice and skip the rsync step (which + # wouldn't work anyway, as source and target folder are the same). + my $stage1Root = dirname($source); + my $nfsRoot = dirname($target); + chomp(my $canonicalStage1Root = qx{readlink -f $stage1Root} || $stage1Root); + chomp(my $canonicalNFSRoot = qx{readlink -f $nfsRoot} || $nfsRoot); + my @mounts = slurpFile('/etc/mtab'); + for my $mount (@mounts) { + if ($mount =~ m{ + ^ + $canonicalStage1Root # mount source + \s+ + $canonicalNFSRoot # mount target + \s+ + none # filesystem for bind mounts is 'none' + \s+ + \S*\bbind\b\S* # look for bind mounts only + }gmsx) { + return 1; + } + } + return 0; +} + +1; diff --git a/src/installer/OpenSLX/OSExport/FileSystem/SquashFS.pm b/src/installer/OpenSLX/OSExport/FileSystem/SquashFS.pm new file mode 100644 index 00000000..77034c9c --- /dev/null +++ b/src/installer/OpenSLX/OSExport/FileSystem/SquashFS.pm @@ -0,0 +1,410 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# SquashFS.pm +# - provides SquashFS-specific overrides of the OpenSLX::OSExport::ExportType +# API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSExport::FileSystem::SquashFS; + +use strict; +use warnings; + +use base qw(OpenSLX::OSExport::FileSystem::Base); + +use File::Basename; +use OpenSLX::Basics; +use OpenSLX::ConfigDB qw(:support); +use OpenSLX::OSExport::FileSystem::Base 1; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {'name' => 'sqfs',}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + my $blockDevice = shift || confess('need to pass in block-device!'); + + $self->SUPER::initialize($engine); + + $self->{'block-device'} = $blockDevice; + my $exportBasePath = "$openslxConfig{'public-path'}/export"; + $self->{'export-path'} = "$exportBasePath/sqfs/$engine->{'vendor-os-name'}"; + return; +} + +sub exportVendorOS +{ + my $self = shift; + my $source = shift; + + my $includeExcludeList = $self->_determineIncludeExcludeList(); + # in order to do the filtering as part of mksquashfs, we need to map + # our internal (rsync-)filter format to regexes: + $includeExcludeList = + $self->_mapRsyncFilter2Regex($source, $includeExcludeList); + vlog(1, _tr("using include-exclude-filter:\n%s\n", $includeExcludeList)); + my $target = $self->{'export-path'}; + + my $sourceTime = (stat($source))[9] || 0; + my $targetTime = (stat($target))[9] || 0; + vlog(2, "source-time=$sourceTime target-time=$targetTime"); + + if ($targetTime && $sourceTime < $targetTime) { + vlog( + 0, + "!!! creation of squashfs skipped, as vendor-OS hasn't changed since last export!\n" + . "!!! Use 'touch $source' to force an export." + ); + } else { + $self->_createSquashFS($source, $target, $includeExcludeList); + } + $self->_addBlockDeviceTagToExport($target); + return; +} + +sub purgeExport +{ + my $self = shift; + + my $target = $self->{'export-path'}; + if ($self->_removeBlockDeviceTagFromExport($target)) { + # no more tags, we can remove the image: + if (slxsystem("rm $target")) { + vlog(0, _tr("unable to remove export '%s'!", $target)); + return 0; + } + } + return 1; +} + +sub checkRequirements +{ + my $self = shift; + my $vendorOSPath = shift; + + # determine most appropriate kernel version ... + my $kernelVer = $self->_pickKernelVersion($vendorOSPath); + + # ... and check if that kernel-version provides all the required modules + my @blockModNames = $self->{'block-device'}->requiredBlockDeviceModules(); + foreach my $blockModName (@blockModNames) { + my $blockMod = + $self->_locateKernelModule($vendorOSPath, "$blockModName.ko", + ["$vendorOSPath/lib/modules/$kernelVer/kernel/drivers/block"]); + if (!defined $blockMod) { + warn _tr( + "unable to find blockdevice-module '%s' for kernel version '%s'.", + $blockModName, $kernelVer + ); + return; + } + } + my $squashfsMod = $self->_locateKernelModule( + $vendorOSPath, + 'squashfs.ko', + [ + "$vendorOSPath/lib/modules/$kernelVer/kernel/fs/squashfs", + "$vendorOSPath/lib/modules/$kernelVer/kernel/fs" + ] + ); + if (!defined $squashfsMod) { + warn _tr("unable to find squashfs-module for kernel version '%s'.", + $kernelVer); + return; + } + return 1; +} + +sub addExportToConfigDB +{ + my $self = shift; + my $export = shift; + my $openslxDB = shift; + + $export->{port} = $self->{'block-device'}->getExportPort($openslxDB); + + my $res = $openslxDB->addExport($export); + return $res; +} + +sub generateExportURI +{ + my $self = shift; + my $export = shift; + my $vendorOS = shift; + + my $URI = $self->{'block-device'}->generateExportURI($export); + $URI .= '/squashfs'; + return $URI; +} + +sub requiredFSMods +{ + my $self = shift; + + my @mods = $self->{'block-device'}->requiredBlockDeviceModules(); + push @mods, 'squashfs '; + return @mods; +} + +sub requiredFSTools +{ + my $self = shift; + + return $self->{'block-device'}->requiredBlockDeviceTools(); +} + +sub showExportConfigInfo +{ + my $self = shift; + my $export = shift; + + $self->{'block-device'}->showExportConfigInfo($export); + return; +} + +################################################################################ +### implementation methods +################################################################################ + +################################################################################# +# Branch to choose the appropriate squashfs version according to target system # +################################################################################ + +sub _createSquashFS +{ + my $self = shift; + my $source = shift; + my $target = shift; + my $includeExcludeList = shift; + + + my @versionString = split(/-/, $self->{engine}->{'vendor-os-name'}); + my $mksquashfsVersion = $self->{engine}->{distro}->getSquashfsVersion($versionString[1]); + + vlog(0, "found version string $versionString[1] out of $self->{engine}->{'vendor-os-name'}"); + vlog(0, "use squashfs version: $mksquashfsVersion"); + + $self->_createSquashFS_prepare($target); + + my $mksquashfsParams; + + $mksquashfsVersion == '3.2' && do + {$mksquashfsParams = $self->_createSquashFS_setup_3_2($includeExcludeList)}; + $mksquashfsVersion == '3.3' && do + {$mksquashfsParams = $self->_createSquashFS_setup_3_3($includeExcludeList)}; + $mksquashfsVersion == '4.0' && do + {$mksquashfsParams = $self->_createSquashFS_setup_4($includeExcludeList)}; + + $self->_createSquashFS_run($source, $target, $mksquashfsParams); + + return; +} + +sub _createSquashFS_prepare +{ + my $self = shift; + my $target = shift; + + system("rm -f $target"); + # mksquasfs isn't significantly faster if fs already exists, but it + # causes the filesystem to grow somewhat, so we remove it in order to + # get the smallest FS-file possible. + + my $baseDir = dirname($target); + if (!-e $baseDir) { + if (system("mkdir -p $baseDir")) { + die _tr("unable to create directory '%s', giving up! (%s)\n", + $baseDir, $!); + } + } + return; +} + + +sub _createSquashFS_run { + my $self = shift; + my $source = shift; + my $target = shift; + my $params = shift; + + # ... invoke mksquashfs ... + vlog(0, _tr("invoking mksquashfs...")); + my $mksquashfsBinary = + "$openslxConfig{'base-path'}/share/squashfs/$params->{binary}"; + my $res = + system("$mksquashfsBinary $source $target $params->{cmdlineOptions}"); + unlink($params->{tmpfile}); + # ... remove filter file if done + if ($res) { + die _tr( + "unable to create squashfs for source '%s' as target '%s', giving up! (%s)", + $source, $target, $!); + } + return; +} + +sub _createSquashFS_setup_4 +{ + my $self = shift; + my $includeExcludeList = shift; + + # dump filter to a file ... + my $filterFile = "/tmp/slx-nbdsquash-filter-$$"; + my $includeFile = "/tmp/slx-nbdsquash-includes-$$"; + spitFile($filterFile, $includeExcludeList); + + slxsystem("sed $filterFile -e '/^-/d' -e 's/^+[ \t]*//' > $includeFile"); + slxsystem("sed -i $filterFile -e '/^+/d' -e 's/^-[ \t]*//'"); + + my $result = { + binary => "mksquashfs_4", + cmdlineOptions => "-wildcards -ef $filterFile", + tmpfile => "$filterFile" + }; + + return $result; +} + + +sub _createSquashFS_setup_3_3 +{ + my $self = shift; + my $includeExcludeList = shift; + + # dump filter to a file ... + my $filterFile = "/tmp/slx-nbdsquash-filter-$$"; + my $includeFile = "/tmp/slx-nbdsquash-includes-$$"; + spitFile($filterFile, $includeExcludeList); + + slxsystem("sed $filterFile -e '/^-/d' -e 's/^+[ \t]*//' > $includeFile"); + slxsystem("sed -i $filterFile -e '/^+/d' -e 's/^-[ \t]*//'"); + + my $result = { + binary => "mksquashfs_3_3", + cmdlineOptions => "-wildcards -ef $filterFile", + tmpfile => "$filterFile" + }; + + return $result; +} + + +sub _createSquashFS_setup_3_2 +{ + my $self = shift; + my $includeExcludeList = shift; + + # dump filter to a file ... + my $filterFile = "/tmp/slx-nbdsquash-filter-$$"; + spitFile($filterFile, $includeExcludeList); + + my $result = { + binary => "mksquashfs_3_2", + cmdlineOptions => "-ff $filterFile", + tmpfile => "$filterFile" + }; + + return $result; +} + +sub _determineIncludeExcludeList +{ + my $self = shift; + + # Rsync uses a first match strategy, so we mix the local specifications + # in front of the filterset given by the package (as the local filters + # should always overrule the vendor filters): + my $distroName = $self->{engine}->{'distro-name'}; + my $localFilterFile = + "$openslxConfig{'config-path'}/distro-info/$distroName/export-filter"; + my $includeExcludeList + = slurpFile($localFilterFile, { failIfMissing => 0 }); + $includeExcludeList .= $self->{engine}->{distro}->{'export-filter'}; + $includeExcludeList =~ s[^\s+][]igms; + # remove any leading whitespace, as rsync doesn't like it + return $includeExcludeList; +} + +sub _mapRsyncFilter2Regex +{ + my $self = shift; + my $sourcePath = shift; + my $rsyncFilter = shift; + + return join( + "\n", + map { + if ($_ =~ m[^([-+]\s*)(.+?)\s*$]) + { + my $action = $1; + my $regex = $2; + $regex =~ s[\*\*][.+]g; + # '**' matches everything + $regex =~ s[\*][[^/]+]g; + # '*' matches anything except slashes + $regex =~ s[\?][[^/]?]g; + # '*' matches any single char except slash + $regex =~ s[\?][[^/]?]g; + # '*' matches any single char except slash + $regex =~ s[\.][\\.]g; + # escape any dots + if (substr($regex, 0, 1) eq '/') { + # absolute path given, need to extend by source-path: + "$action^$sourcePath$regex\$"; + } else { + # filename pattern given, need to anchor to the end only: + "$action$regex\$"; + } + } else { + $_; + } + } + split "\n", + $rsyncFilter + ); +} + +sub _addBlockDeviceTagToExport +{ + my $self = shift; + my $target = shift; + + my $tagName = "$target" . '@' . lc($self->{'block-device'}->{name}); + linkFile(basename($target), $tagName); + return; +} + +sub _removeBlockDeviceTagFromExport +{ + my $self = shift; + my $target = shift; + + my $tagName = "$target" . '@' . lc($self->{'block-device'}->{name}); + slxsystem("rm $tagName"); + # now find out whether or not there are any other tags left: + my $vendorOSName = basename($target); + opendir(DIR, dirname($target)); + my @tags = grep { /^$vendorOSName\@/ } readdir(DIR); + return @tags ? 0 : 1; + # return 1 if no more tags (i.e. it is safe to remove the image) +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Distro/Any_Clone.pm b/src/installer/OpenSLX/OSSetup/Distro/Any_Clone.pm new file mode 100644 index 00000000..43385a29 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Any_Clone.pm @@ -0,0 +1,31 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Any_Clone.pm +# - provides generic clone-only overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Any_Clone; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/Distro/Base.pm b/src/installer/OpenSLX/OSSetup/Distro/Base.pm new file mode 100644 index 00000000..c356e6d9 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Base.pm @@ -0,0 +1,371 @@ +# Copyright (c) 2006..2010 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Base.pm +# - provides base implementation of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use Fcntl qw(:DEFAULT :flock); +use File::Basename; +use File::Path; +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSSetup::System::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between distro and its engine + + if ($engine->{'distro-name'} =~ m[x86_64]) { + # be careful to only try installing 64-bit systems if actually + # running on a 64-bit host, as otherwise we are going to fail later, + # anyway: + my $arch = `uname -m`; + if ($?) { + die _tr("unable to determine architecture of host system (%s)\n", $!); + } + if ($arch !~ m[x86_64]) { + die _tr("you can't install a 64-bit system on a 32-bit host, sorry!\n"); + } + } + + $self->{'stage1a-binaries'} = { + "$openslxConfig{'base-path'}/share/busybox/busybox" => 'bin', + }; + + $self->{'stage1b-faked-files'} = [ + '/etc/mtab', + ]; + + $self->{'stage1c-faked-files'} = [ + ]; + + $self->{'clone-filter'} = " + + /var + - /var/tmp/* + - /var/spool/* + - /var/cache/apt/archives/*.deb + - /var/cache/apt/archives/lock + - /var/cache/apt/archives/partial/* + + /var/cache/apt/archives/partial + - /var/tmp/* + + /var/tmp/apt + - /var/opt/openslx + - /var/lib/vmware + - /var/lib/ntp/* + - /var/run/* + + /var/run/screen + - /var/log/* + + /var/log/apt + - /usr/lib/vmware/modules/* + + /usr + - /tmp/* + + /tmp + - /sys/* + + /sys + + /sbin + - /root/* + + /root + - /proc/* + + /proc + - /opt/openslx + + /opt + - /media/* + + /media + - /mnt/* + + /mnt + + /lib64 + - /lib/ld-uClibc* + + /lib + - /home/* + + /home + - /etc/vmware/* + + /etc/vmware + - /etc/vmware-installer + - /etc/grub* + - /etc/shadow* + - /etc/samba/secrets.tdb + - /etc/resolv.conf.* + - /etc/opt/openslx + + /etc/opt/openslx + - /etc/exports* + - /etc/X11/xorg.* + - /etc/X11/XF86* + + /etc + - /dev/* + + /dev + + /boot + + /bin + - /* + - .svn + - .git + - .*.cmd + - *~ + - *lost+found* + - *.old + - *.bak + "; + + return; +} + +sub fixPrerequiredFiles +{ +} + +sub startSession +{ + my $self = shift; + my $osDir = shift; + + # setup a fixed locale environment to avoid warnings about unset locales + # (like for instance shown by apt-get) + $ENV{LC_ALL} = 'POSIX'; + + # ensure that a couple of important devices exist + my %devInfo = ( + mem => { type => 'c', major => '1', minor => '1' }, + null => { type => 'c', major => '1', minor => '3' }, + zero => { type => 'c', major => '1', minor => '5' }, + random => { type => 'c', major => '1', minor => '8' }, + urandom => { type => 'c', major => '1', minor => '9' }, + kmsg => { type => 'c', major => '1', minor => '11' }, + tty => { type => 'c', major => '5', minor => '0' }, + console => { type => 'c', major => '5', minor => '1' }, + ptmx => { type => 'c', major => '5', minor => '2' }, + ); + if (!-e "$osDir/dev" && !mkpath("$osDir/dev")) { + die _tr("unable to create folder '%s' (%s)\n", "$osDir/dev", $!); + } + foreach my $dev (keys %devInfo) { + my $info = $devInfo{$dev}; + if (!-e "$osDir//dev/$dev") { + if (slxsystem( + "mknod $osDir//dev/$dev $info->{type} $info->{major} $info->{minor}" + )) { + croak(_tr("unable to create dev-node '%s'! (%s)", $dev, $!)); + } + } + } + + # enter chroot jail + chrootInto($osDir); + $ENV{PATH} = join(':', @{$self->getDefaultPathList()}); + + # mount /proc (if we have 'mount' available) + if (qx{which mount 2>/dev/null}) { + if (!-e '/proc' && !mkpath('/proc')) { + die _tr("unable to create folder '%s' (%s)\n", "$osDir/proc", $!); + } + if (slxsystem("mount -t proc proc '/proc'")) { + warn _tr("unable to mount '%s' (%s)\n", "$osDir/proc", $!); + } + if (!-e '/dev/pts' && !mkpath('/dev/pts')) { + die _tr("unable to create folder '%s' (%s)\n", "$osDir/dev/pts", $!); + } + if (slxsystem("mount -t devpts devpts '/dev/pts'")) { + warn _tr("unable to mount '%s' (%s)\n", "$osDir/dev/pts", $!); + } + } + + return 1; +} + +sub finishSession +{ + my $self = shift; + + # umount /proc, /dev/pts (if we have 'umount' available) + if (qx{which umount 2>/dev/null}) { + if (slxsystem("umount /proc")) { + warn _tr("unable to umount '%s' (%s)\n", "/proc", $!); + } + if (slxsystem("umount /dev/pts")) { + warn _tr("unable to umount '%s' (%s)\n", "/dev/pts", $!); + } + } + + return 1; +} + +sub getDefaultPathList +{ + my $self = shift; + + return [ qw( + /sbin + /usr/sbin + /usr/local/sbin + /usr/local/bin + /usr/bin + /bin + /usr/bin/X11 + /usr/X11R6/bin + /opt/kde3/bin + /opt/gnome/bin + ) ]; +} + +sub updateDistroConfig +{ + if (slxsystem("ldconfig")) { + die _tr("unable to run ldconfig (%s)", $!); + } +} + +sub pickKernelFile +{ + 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); + } + return $newestKernelFile; +} + +sub preSystemInstallationHook +{ +} + +sub postSystemInstallationHook +{ +} + +sub setPasswordForUser +{ + my $self = shift; + my $username = shift; + my $password = shift; + + my $hashedPassword = $self->hashPassword($password); + + my $writePasswordFunction = sub { + # now read, change and write shadow-file in atomic manner: + my $shadowFile = '/etc/shadow'; + if (!-e $shadowFile) { + spitFile( $shadowFile, ''); + } + slxsystem("cp -r $shadowFile $shadowFile~"); + my $shadowFH; + open($shadowFH, '+<', $shadowFile) + or croak _tr("could not open file '%s'! (%s)", $shadowFile, $!); + flock($shadowFH, LOCK_EX) + or croak _tr("could not lock file '%s'! (%s)", $shadowFile, $!); + my $lastChanged = int(time()/24/60/60); + my $newEntry + = "$username:$hashedPassword:$lastChanged:0:99999:7:::"; + my $content = do { local $/; <$shadowFH> }; + if ($content =~ m{^$username:}ims) { + $content =~ s{^$username:.+?$}{$newEntry}ms; + } else { + $content .= "$newEntry\n"; + } + seek($shadowFH, 0, 0) + or croak _tr("could not seek file '%s'! (%s)", $shadowFile, $!); + print $shadowFH $content + or croak _tr("could not write to file '%s'! (%s)", $shadowFile, $!); + close($shadowFH) + or croak _tr("could not close file '%s'! (%s)", $shadowFile, $!); + unlink "$shadowFile~"; + }; + $self->{engine}->callChrootedFunctionForVendorOS($writePasswordFunction); +} + +sub hashPassword +{ + my $self = shift; + my $password = shift; + + my $busyboxBin = $self->{engine}->busyboxBinary(); + my $hashedPassword = qx{$busyboxBin cryptpw -a md5 $password}; + chomp $hashedPassword; + + return $hashedPassword; +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSSetup::System::Base - the base class for all OSSetup backends + +=head1 SYNOPSIS + + package OpenSLX::OSSetup::coolnewOS; + + use vars qw(@ISA $VERSION); + @ISA = ('OpenSLX::OSSetup::Base'); + $VERSION = 1.01; + + use coolnewOS; + + sub new + { + my $class = shift; + my $self = {}; + return bless $self, $class; + } + + # override all methods of OpenSLX::OSSetup::Base in order to implement + # a full OS-setup backend + ... + +I> + +=head1 DESCRIPTION + +This class defines the OSSetup interface for the OpenSLX. + +Aim of the OSSetup abstraction is to make it possible to install a large set +of different operating systems transparently. + +... + +=cut diff --git a/src/installer/OpenSLX/OSSetup/Distro/Debian.pm b/src/installer/OpenSLX/OSSetup/Distro/Debian.pm new file mode 100644 index 00000000..bdb9dcc1 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Debian.pm @@ -0,0 +1,135 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Debian.pm +# - provides Debian-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Debian; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + $self->{'packager-type'} = 'dpkg'; + $self->{'meta-packager-type'} = $ENV{SLX_META_PACKAGER} || 'apt'; + $self->{'stage1c-faked-files'} = []; + return; +} + +sub preSystemInstallationHook +{ + my $self = shift; + + $self->SUPER::preSystemInstallationHook(); + + # create required /dev-entries + my %devInfo = ( + mem => { type => 'c', major => '1', minor => '1' }, + null => { type => 'c', major => '1', minor => '3' }, + zero => { type => 'c', major => '1', minor => '5' }, + random => { type => 'c', major => '1', minor => '8' }, + urandom => { type => 'c', major => '1', minor => '9' }, + kmsg => { type => 'c', major => '1', minor => '11' }, + console => { type => 'c', major => '5', minor => '1' }, + ptmx => { type => 'c', major => '5', minor => '2' }, + ); + foreach my $dev (keys %devInfo) { + my $info = $devInfo{$dev}; + if (!-e "/dev/$dev") { + if (slxsystem( + "mknod /dev/$dev $info->{type} $info->{major} $info->{minor}" + )) { + croak(_tr("unable to create dev-node '%s'! (%s)", $dev, $!)); + } + } + } + foreach my $devDir ('pts', 'shm', '.udevdb', '.udev') { + if (!-e "/dev/$devDir") { + if (slxsystem("mkdir -p /dev/$devDir")) { + croak(_tr("unable to create dev-dir '%s'! (%s)", $devDir, $!)); + } + } + } + + # replace /usr/sbin/invoke-rc.d by a dummy, in order to avoid a whole lot + # of initscripts being started. Wishful thinking: there should be another + # way to stop Debian from doing this, as this is not really very supportive + # of folder-based installations (then again: I may simply be too stupid + # to find out how it is supposed to work ...) + rename('/usr/sbin/invoke-rc.d', '/usr/sbin/_invoke-rc.d'); + spitFile('/usr/sbin/invoke-rc.d', "#! /bin/sh\nexit 0\n"); + chmod 0755, '/usr/sbin/invoke-rc.d'; +} + +sub startSession +{ + my $self = shift; + my $osDir = shift; + + $self->SUPER::startSession($osDir); + + # As in preSystemInstallationHook, we replace /usr/sbin/invoke-rc.d by a + # dummy. + # + # During installation, this might not exist yet, so we better check + if (-e '/usr/sbin/invoke-rc.d') { + rename('/usr/sbin/invoke-rc.d', '/usr/sbin/_invoke-rc.d'); + spitFile('/usr/sbin/invoke-rc.d', "#! /bin/sh\nexit 0\n"); + chmod 0755, '/usr/sbin/invoke-rc.d'; + } +} + +sub finishSession +{ + my $self = shift; + + # restore /usr/sbin/invoke-rc.d + rename('/usr/sbin/_invoke-rc.d', '/usr/sbin/invoke-rc.d'); + + $self->SUPER::finishSession(); +} + +sub setPasswordForUser +{ + my $self = shift; + my $username = shift; + my $password = shift; + + # activate shadow passwords + my $activateShadowFunction = sub { + slxsystem('/sbin/shadowconfig', 'on'); + }; + $self->{engine}->callChrootedFunctionForVendorOS($activateShadowFunction); + + # invoke default behaviour + $self->SUPER::setPasswordForUser($username, $password); +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/Distro/Debian_3_1.pm b/src/installer/OpenSLX/OSSetup/Distro/Debian_3_1.pm new file mode 100644 index 00000000..03c6fdf9 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Debian_3_1.pm @@ -0,0 +1,74 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Debian_3_1.pm +# - provides Debian-3.1-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Debian_3_1; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Debian); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub preSystemInstallationHook +{ + my $self = shift; + + $self->SUPER::preSystemInstallationHook(); + + # when the kernel package is being configured, it insists on trying to + # create an initrd, which neither works nor makes sense in our environment. + # + # in order to circumvent this problem, we manually install initrd-tools + # (which contains mkinitrd) ... + $self->{engine}->{'meta-packager'}->installPackages('initrd-tools'); + # ... and replace /usr/sbin/mkinitrd with a dummy, in order to skip the + # initrd-creation. + rename('/usr/sbin/mkinitrd', '/usr/sbin/_mkinitrd'); + spitFile('/usr/sbin/mkinitrd', "#! /bin/sh\ntouch \$2\n"); + chmod 0755, '/usr/sbin/mkinitrd'; +} + +sub startSession +{ + my $self = shift; + my $osDir = shift; + + $self->SUPER::startSession($osDir); + + # As in preSystemInstallationHook, we replace /usr/sbin/mkinitrd with a + # dummy, in order to skip the initrd-creation. + # + # During installation, this might not exist yet, so we better check + if (-e '/usr/sbin/mkinitrd') { + rename('/usr/sbin/mkinitrd', '/usr/sbin/_mkinitrd'); + spitFile('/usr/sbin/mkinitrd', "#! /bin/sh\ntouch \$2\n"); + chmod 0755, '/usr/sbin/mkinitrd'; + } +} + +sub finishSession +{ + my $self = shift; + + # restore /usr/sbin/mkinitrd + rename('/usr/sbin/_mkinitrd', '/usr/sbin/mkinitrd'); + + $self->SUPER::finishSession(); +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/Distro/Fedora.pm b/src/installer/OpenSLX/OSSetup/Distro/Fedora.pm new file mode 100644 index 00000000..80480340 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Fedora.pm @@ -0,0 +1,48 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Fedora.pm +# - provides Fedora-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Fedora; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + $self->{'packager-type'} = 'rpm'; + $self->{'meta-packager-type'} = $ENV{SLX_META_PACKAGER} || 'yum'; + $self->{'stage1c-faked-files'} = [ + '/etc/fstab', + '/etc/mtab', + ]; + return; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/Distro/Gentoo.pm b/src/installer/OpenSLX/OSSetup/Distro/Gentoo.pm new file mode 100644 index 00000000..79fd0e29 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Gentoo.pm @@ -0,0 +1,33 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Gentoo.pm +# - provides Gentoo-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Gentoo; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Distro/Scilin.pm b/src/installer/OpenSLX/OSSetup/Distro/Scilin.pm new file mode 100644 index 00000000..e1ce5fc3 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Scilin.pm @@ -0,0 +1,48 @@ +# Copyright (c) 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Scilin.pm +# - provides Scientific Linux specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Scilin; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + $self->{'packager-type'} = 'rpm'; + $self->{'meta-packager-type'} = $ENV{SLX_META_PACKAGER} || 'yum'; + $self->{'stage1c-faked-files'} = [ + '/etc/fstab', + '/etc/mtab', + ]; + return; +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Distro/Suse.pm b/src/installer/OpenSLX/OSSetup/Distro/Suse.pm new file mode 100644 index 00000000..8e85e46a --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Suse.pm @@ -0,0 +1,98 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Suse.pm +# - provides SUSE-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Suse; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + $self->{'packager-type'} = 'rpm'; + + # use 'zypper' as meta-packager from 10.2 onwards and use 'smart' for + # older releases + my $defaultMetaPackager = 'zypper'; + if ($self->{'engine'}->{'distro-name'} =~ m{-([^-]+)$}) { + my $distroVersion = 0.0 + $1; + if ($distroVersion <= 10.2) { + $defaultMetaPackager = 'smart'; + } + } + $self->{'meta-packager-type'} + = $ENV{SLX_META_PACKAGER} || $defaultMetaPackager; + + if ($engine->{'action-type'} eq 'install') { + # Inform SUSE RPMs that we're performing an installation - this is + # only important for installations taking place in stage 1c: + $ENV{YAST_IS_RUNNING} = "instsys"; + } + + return; +} + +sub fixPrerequiredFiles +{ + my $self = shift; + my $stage1cDir = shift; + + chown( + 0, 0, "$stage1cDir/etc/group", "$stage1cDir/etc/passwd", + "$stage1cDir/etc/shadow" + ); + return; +} + +sub updateDistroConfig +{ + my $self = shift; + + # invoke SuSEconfig in order to allow it to update the configuration: + if (slxsystem('SuSEconfig')) { + die _tr("unable to run SuSEconfig (%s)", $!); + } + $self->SUPER::updateDistroConfig(); + return; +} + +sub hashPassword +{ + my $self = shift; + my $password = shift; + + my $busyboxBin = $self->{engine}->busyboxBinary(); + my $hashedPassword = qx{$busyboxBin cryptpw -a blowfish '$password'}; + chomp $hashedPassword; + + return $hashedPassword; +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Distro/Ubuntu.pm b/src/installer/OpenSLX/OSSetup/Distro/Ubuntu.pm new file mode 100644 index 00000000..f0f42487 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Distro/Ubuntu.pm @@ -0,0 +1,119 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# OSSetup/Distro/Ubuntu.pm +# - provides Ubuntu-specific overrides of the OSSetup Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Distro::Ubuntu; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Distro::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = {}; + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->SUPER::initialize($engine); + $self->{'packager-type'} = 'dpkg'; + $self->{'meta-packager-type'} = $ENV{SLX_META_PACKAGER} || 'apt'; + $self->{'stage1c-faked-files'} = []; + return; +} + +sub preSystemInstallationHook +{ + my $self = shift; + + $self->SUPER::preSystemInstallationHook(); + + # fake required /dev-entries + my %devInfo = ( + mem => { type => 'c', major => '1', minor => '1' }, + null => { type => 'c', major => '1', minor => '3' }, + zero => { type => 'c', major => '1', minor => '5' }, + random => { type => 'c', major => '1', minor => '8' }, + urandom => { type => 'c', major => '1', minor => '9' }, + kmsg => { type => 'c', major => '1', minor => '11' }, + console => { type => 'c', major => '5', minor => '1' }, + ptmx => { type => 'c', major => '5', minor => '2' }, + ); + foreach my $dev (keys %devInfo) { + my $info = $devInfo{$dev}; + if (!-e "/dev/$dev") { + if (slxsystem( + "mknod /dev/$dev $info->{type} $info->{major} $info->{minor}" + )) { + croak(_tr("unable to create dev-node '%s'! (%s)", $dev, $!)); + } + } + } + foreach my $devDir ('pts', 'shm', '.udevdb', '.udev') { + if (!-e "/dev/$devDir") { + if (slxsystem("mkdir -p /dev/$devDir")) { + croak(_tr("unable to create dev-dir '%s'! (%s)", $devDir, $!)); + } + } + } + + # replace /usr/sbin/invoke-rc.d by a dummy, in order to avoid a whole lot + # of initscripts being started. Wishful thinking: there should be another + # way to stop Ubuntu from doing this, as this is not really very supportive + # of folder-based installations (then again: I may simply be too stupid + # to find out how it is supposed to work ...) + rename('/usr/sbin/invoke-rc.d', '/usr/sbin/_invoke-rc.d'); + spitFile('/usr/sbin/invoke-rc.d', "#! /bin/sh\nexit 0\n"); + chmod 0755, '/usr/sbin/invoke-rc.d'; +} + +sub startSession +{ + my $self = shift; + my $osDir = shift; + + $self->SUPER::startSession($osDir); + + # As in preSystemInstallationHook, we replace /usr/sbin/invoke-rc.d by a + # dummy. + # + # During installation, this might not exist yet, so we better check + if (-e '/usr/sbin/invoke-rc.d') { + rename('/usr/sbin/invoke-rc.d', '/usr/sbin/_invoke-rc.d'); + spitFile('/usr/sbin/invoke-rc.d', "#! /bin/sh\nexit 0\n"); + chmod 0755, '/usr/sbin/invoke-rc.d'; + } +} + +sub finishSession +{ + my $self = shift; + + # restore /usr/sbin/invoke-rc.d + rename('/usr/sbin/_invoke-rc.d', '/usr/sbin/invoke-rc.d'); + + $self->SUPER::finishSession(); +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Engine.pm b/src/installer/OpenSLX/OSSetup/Engine.pm new file mode 100644 index 00000000..642a058b --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Engine.pm @@ -0,0 +1,1929 @@ +# Copyright (c) 2006..2010 - 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/ +# ----------------------------------------------------------------------------- +# Engine.pm +# - provides driver engine for the OSSetup API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Engine; + +use strict; +use warnings; + +our (@ISA, @EXPORT, $VERSION); +$VERSION = 1.01; # API-version . implementation-version + +use Exporter; +@ISA = qw(Exporter); + +@EXPORT = qw( + %supportedDistros +); + +use Config::General; +use File::Basename; +use File::Path; +use URI; + +use OpenSLX::Basics; +use OpenSLX::ScopedResource; +use OpenSLX::Syscall; +use OpenSLX::Utils; + +use vars qw(%supportedDistros); + +%supportedDistros = ( + 'debian-3.1' => 'clone,install,update,shell', + 'debian-4.0' => 'clone,install,update,shell', + 'debian-4.0_amd64' => 'clone,install,update,shell', + 'debian-5.0' => 'clone,update,shell', + 'fedora-6' => 'clone,install,update,shell', + 'fedora-6_x86_64' => 'clone,install,update,shell', + 'gentoo-2007.X' => 'clone', + 'suse-10.1' => 'clone,install,update,shell', + 'suse-10.1_x86_64' => 'clone,install,update,shell', + 'suse-10.2' => 'clone,install,update,shell', + 'suse-10.2_x86_64' => 'clone,install,update,shell', + 'suse-10.3' => 'clone,install,update,shell', + 'suse-10.3_x86_64' => 'clone,update,shell', + 'suse-11.0' => 'clone,install,update,shell', + 'suse-11.0_x86_64' => 'clone,update,shell', + 'suse-11.1' => 'clone,install,update,shell', + 'suse-11.1_x86_64' => 'clone,update,shell', + 'suse-11.2' => 'clone,install,update,shell', + 'suse-11.2_x86_64' => 'clone,update,shell', + 'suse-11.3' => 'clone,update,shell', + 'suse-11.3_x86_64' => 'clone,update,shell', + 'scilin-4.7' => 'clone,update,shell', + 'scilin-5.3' => 'clone,update,shell', + 'scilin-5.4_x86_64' => 'clone,update,shell', + 'scilin-5.5_x86_64' => 'clone,update,shell', + 'ubuntu-8.04' => 'clone,install,update,shell', + 'ubuntu-8.04_amd64' => 'clone,update,shell', + 'ubuntu-8.10' => 'clone,install,update,shell', + 'ubuntu-8.10_amd64' => 'clone,update,shell', + 'ubuntu-9.04' => 'clone,install,update,shell', + 'ubuntu-9.04_amd64' => 'clone,update,shell', + 'ubuntu-9.10' => 'clone,install,update,shell', + 'ubuntu-9.10_amd64' => 'clone,update,shell', + 'ubuntu-10.04' => 'clone,install,update,shell', + 'ubuntu-10.04_amd64'=> 'clone,update,shell', +); + +my %localHttpServers; +my $filelisting; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + + my $self = {}; + + return bless $self, $class; +} + +sub initialize +{ + my $self = shift; + my $vendorOSName = shift; + my $actionType = shift; + + if ($vendorOSName eq '<<>>') { + die _tr("you can't do that with the default vendor-OS!\n"); + } + if ($vendorOSName !~ m[^([^\-]+\-[^\-]+)(?:\-(.+))?]) { + die _tr( + "Given vendor-OS has unknown format, " . + "expected '-[-]'\n" + ); + } + my $distroName = lc($1); + my $selectionName = $2 || 'default'; + $self->{'vendor-os-name'} = $vendorOSName; + $self->{'action-type'} = $actionType; + $self->{'distro-name'} = $distroName; + $self->{'selection-name'} = $selectionName; + $self->{'clone-source'} = ''; + if (!exists $supportedDistros{$distroName}) { + print _tr("Sorry, distro '%s' is unsupported.\n", $distroName); + print _tr("List of supported distros:\n\t"); + print join("\n\t", sort keys %supportedDistros) . "\n"; + exit 1; + } + my $support = $supportedDistros{$distroName}; + if ($actionType eq 'install' && $support !~ m[install]i) { + print _tr( + "Sorry, distro '%s' can not be installed, only cloned!\n", + $distroName + ); + exit 1; + } + elsif ($actionType eq 'update' && $support !~ m[(update)]i) { + print _tr( + "Sorry, update support for vendor-OS '%s' has not been " . + "implemented!\n", + $distroName + ); + exit 1; + } + elsif ($actionType eq 'shell' && $support !~ m[(shell)]i) { + print _tr( + "Sorry, vendor-OS '%s' has no support for chrooted shells " . + "available!\n", + $distroName + ); + exit 1; + } + + # load module for the requested distro: + my $distro = loadDistroModule({ + distroName => $distroName, + distroScope => 'OpenSLX::OSSetup::Distro', + fallbackName => 'Any_Clone', + }); + if (!$distro) { + die _tr( + 'unable to load any OSSetup::Distro module for vendor-OS %s!', + $vendorOSName + ); + } + + $distro->initialize($self); + $self->{distro} = $distro; + + # protect against parallel executions of writing OpenSLX scripts + $self->{'vendor-os-lock'} = grabLock($vendorOSName); + + if ($actionType =~ m{^(install|update|shell|plugin)}) { + # setup path to distribution-specific info: + my $sharedDistroInfoDir + = "$openslxConfig{'base-path'}/share/distro-info/" . + "$self->{'distro-name'}"; + if (!-d $sharedDistroInfoDir) { + die _tr( + "unable to find shared distro-info in '%s'\n", + $sharedDistroInfoDir + ); + } + $self->{'shared-distro-info-dir'} = $sharedDistroInfoDir; + my $configDistroInfoDir = + "$openslxConfig{'config-path'}/distro-info/$self->{'distro-name'}"; + if (!-d $configDistroInfoDir) { + die _tr( + "unable to find configurable distro-info in '%s'\n", + $configDistroInfoDir + ); + } + $self->{'config-distro-info-dir'} = $configDistroInfoDir; + + my $setupMirrorsIfNecessary = $actionType eq 'install'; + $self->_readDistroInfo($setupMirrorsIfNecessary); + } + + if ($self->{'action-type'} eq 'install' + && !exists $self->{'distro-info'}->{'selection'}->{$selectionName}) + { + die( + _tr( + "selection '%s' is unknown to distro '%s'\n", + $selectionName, $self->{'distro-name'} + ) + . _tr("These selections are available:\n\t") + . join("\n\t", sort keys %{$self->{'distro-info'}->{'selection'}}) + . "\n" + ); + } + + $self->{'vendor-os-path'} + = "$openslxConfig{'private-path'}/stage1/$self->{'vendor-os-name'}"; + vlog(1, "vendor-OS path is '$self->{'vendor-os-path'}'"); + + if ($actionType =~ m{^(install|update|shell|plugin)}) { + $self->_createPackager(); + $self->_createMetaPackager(); + } + + return; +} + +sub installVendorOS +{ + my $self = shift; + my $vendorOSSettings = shift; + + my $installInfoFile = "$self->{'vendor-os-path'}/.openslx-install-info"; + if (-e $installInfoFile) { + die _tr("vendor-OS '%s' already exists, giving up!\n", + $self->{'vendor-os-path'}); + } + $self->_createVendorOSPath(); + + my $httpServers = OpenSLX::ScopedResource->new({ + name => 'local-http-servers', + acquire => sub { $self->_startLocalURLServersAsNeeded(); 1 }, + release => sub { $self->_stopLocalURLServers(); 1 }, + }); + + my $baseSystemFile = "$self->{'vendor-os-path'}/.openslx-base-system"; + if (-e $baseSystemFile) { + vlog(0, _tr("found existing base system, continuing...\n")); + } + else { + # basic setup, stage1a-c: + $self->_setupStage1A(); + callInSubprocess( + sub { + # some tasks that involve a chrooted environment: + $self->_changePersonalityIfNeeded(); + $self->_setupStage1B(); + $self->_setupStage1C(); + } + ); + $self->_stage1C_cleanupBasicVendorOS(); + # just touch the file, in order to indicate a basic system: + slxsystem("touch $baseSystemFile"); + } + callInSubprocess( + sub { + # another task that involves a chrooted environment: + $self->_changePersonalityIfNeeded(); + $self->_setupStage1D(); + } + ); + + # create the install-info file, in order to indicate a proper installation: + spitFile( + $installInfoFile, + "SLX_META_PACKAGER=$self->{distro}->{'meta-packager-type'}\n" + ); + + # base system info file is no longer needed, we have a full system now + slxsystem("rm $baseSystemFile"); + + $self->_applyVendorOSSettings($vendorOSSettings) unless !$vendorOSSettings; + + vlog( + 0, + _tr( + "Vendor-OS '%s' installed succesfully.\n", + $self->{'vendor-os-name'} + ) + ); + + # generate default openslx directories for the client + $self->_generateDefaultDirs(); + + # add the uclibs and tools to the stage1 + $self->_copyUclibcRootfs(); + #callInSubprocess( + # sub { + # $self->_callChrootedFunction({ + # chrootDir => $self->{'vendor-os-path'}, + # function => sub { + # $self->{'distro'}->addUclibLdconfig(); + # }, + # updateConfig => 1, + # }); + #}); + $self->_touchVendorOS(); + $self->addInstalledVendorOSToConfigDB(); + return; +} + +sub cloneVendorOS +{ + my $self = shift; + my $source = shift; + + if (substr($source, -1, 1) ne '/') { + # make sure source path ends with a slash, as otherwise, the + # last folder would be copied (but we only want its contents). + $source .= '/'; + } + + $self->{'clone-source'} = $source; + my $lastCloneSource = ''; + my $cloneInfoFile = "$self->{'vendor-os-path'}/.openslx-clone-info"; + my $isReClone; + if (-e $self->{'vendor-os-path'}) { + my $installInfoFile = "$self->{'vendor-os-path'}/.openslx-install-info"; + if (-e $installInfoFile) { + # oops, given vendor-os has been installed, not cloned, we complain: + croak( + _tr( + "The vendor-OS '%s' exists but it is no clone, refusing " . + "to clobber!\nPlease delete the folder manually, if " . + "that's really what you want...\n", + $self->{'vendor-os-path'} + ) + ); + } + elsif (-e $cloneInfoFile) { + # check if last and current source match: + my $cloneInfo = slurpFile($cloneInfoFile); + if ($cloneInfo =~ m[^source\s*=\s*(.+?)\s*$]ims) { + $lastCloneSource = $1; + } + if ($source ne $lastCloneSource) { + # protect user from confusing sources (still allowed, though): + my $yes = _tr('yes'); + my $no = _tr('no'); + print _tr( + "Last time this vendor-OS was cloned, it has been cloned " . + "from '%s', now you specified a different source: '%s'\n" . + "Would you still like to proceed (%s/%s)?", + $lastCloneSource, $source, $yes, $no + ); + my $answer = ; + exit 5 unless $answer =~ m[^\s*$yes]i; + } + $isReClone = 1; + } + else { + # Neither the install-info nor the clone-info file exists. This + # probably means that the folder has been created by an older + # version of the tools. There's not much we can do, we simply + # trust our user and assume that he knows what he's doing. + } + } + + $self->_createVendorOSPath(); + + $self->_clone_fetchSource($source); + if ($source ne $lastCloneSource) { + spitFile($cloneInfoFile, "source=$source\n"); + } + if ($isReClone) { + vlog( + 0, + _tr( + "Vendor-OS '%s' has been re-cloned succesfully.\n", + $self->{'vendor-os-name'} + ) + ); + } + else { + vlog( + 0, + _tr( + "Vendor-OS '%s' has been cloned succesfully.\n", + $self->{'vendor-os-name'} + ) + ); + } + + # generate default openslx directories for the client + $self->_generateDefaultDirs(); + + # add the uclibs and tools to the stage1 + $self->_copyUclibcRootfs(); + $self->_touchVendorOS(); + $self->addInstalledVendorOSToConfigDB(); + return; +} + +sub updateVendorOS +{ + my $self = shift; + + if (!-e $self->{'vendor-os-path'}) { + die _tr("can't update vendor-OS '%s', since it doesn't exist!\n", + $self->{'vendor-os-path'}); + } + + my $httpServers = OpenSLX::ScopedResource->new({ + name => 'local-http-servers', + acquire => sub { $self->_startLocalURLServersAsNeeded(); 1 }, + release => sub { $self->_stopLocalURLServers(); 1 }, + }); + + callInSubprocess( + sub { + $self->_changePersonalityIfNeeded(); + $self->_updateStage1D(); + } + ); + + $self->_generateDefaultDirs(); + $self->_copyUclibcRootfs(); + $self->_touchVendorOS(); + vlog( + 0, + _tr("Vendor-OS '%s' updated succesfully.\n", $self->{'vendor-os-name'}) + ); + + $self->_installPlugins(); + + return; +} + +sub startChrootedShellForVendorOS +{ + my $self = shift; + + if (!-e $self->{'vendor-os-path'}) { + die _tr( + "can't start chrooted shell for vendor-OS '%s', since it doesn't " . + "exist!\n", + $self->{'vendor-os-path'} + ); + } + + my $httpServers = OpenSLX::ScopedResource->new({ + name => 'local-http-servers', + acquire => sub { $self->_startLocalURLServersAsNeeded(); 1 }, + release => sub { $self->_stopLocalURLServers(); 1 }, + }); + + callInSubprocess( + sub { + $self->_changePersonalityIfNeeded(); + $self->_startChrootedShellInStage1D(); + } + ); + + vlog( + 0, + _tr( + "Chrooted shell for vendor-OS '%s' has been closed.\n", + $self->{'vendor-os-name'} + ) + ); + $self->_touchVendorOS(); + + return; +} + +sub callChrootedFunctionForVendorOS +{ + my $self = shift; + my $function = shift; + my $updateConfig = shift || 0; + + if (!-e $self->{'vendor-os-path'}) { + die _tr( + "can't call chrooted function for vendor-OS '%s', since it " . + "doesn't exist!\n", + $self->{'vendor-os-path'} + ); + } + + # avoid trying to chroot into a 64-bit vendor-OS if the host is only 32-bit: + if (!$self->_hostIs64Bit() && -e "$self->{'vendor-os-path'}/lib64") { + die _tr("you can't use a 64-bit vendor-OS on a 32-bit host, sorry!\n"); + } + + my $httpServers = OpenSLX::ScopedResource->new({ + name => 'local-http-servers', + acquire => sub { $self->_startLocalURLServersAsNeeded(); 1 }, + release => sub { $self->_stopLocalURLServers(); 1 }, + }); + + callInSubprocess( + sub { + $self->_changePersonalityIfNeeded(); + $self->_callChrootedFunction({ + chrootDir => $self->{'vendor-os-path'}, + function => $function, + updateConfig => $updateConfig, + }); + } + ); + + vlog( + 1, + _tr( + "Chrooted function for vendor-OS '%s' has finished.\n", + $self->{'vendor-os-name'} + ) + ); + $self->_touchVendorOS(); + + return 1; +} + +sub removeVendorOS +{ + my $self = shift; + + vlog( + 0, + _tr("removing vendor-OS folder '%s'...", $self->{'vendor-os-path'}) + ); + if (system( + "find $self->{'vendor-os-path'} -xdev -depth -print0 | xargs -0 rm -r" + )) { + vlog( + 0, + _tr("* unable to remove vendor-OS '%s'!", $self->{'vendor-os-path'}) + ); + } + else { + vlog( + 0, + _tr( + "Vendor-OS '%s' removed succesfully.\n", + $self->{'vendor-os-name'} + ) + ); + } + $self->removeVendorOSFromConfigDB(); + return; +} + +sub addInstalledVendorOSToConfigDB +{ + my $self = shift; + + if (!-e $self->{'vendor-os-path'}) { + die _tr( + "can't import vendor-OS '%s', since it doesn't exist!\n", + $self->{'vendor-os-path'} + ); + } + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + my @plugins; + + # insert new vendor-os if it doesn't already exist in DB: + my $vendorOSName = $self->{'vendor-os-name'}; + my $vendorOS = $openslxDB->fetchVendorOSByFilter({'name' => $vendorOSName}); + if (defined $vendorOS) { + if ($vendorOS->{'clone_source'} + && $self->{'clone-source'} ne $vendorOS->{'clone_source'}) { + $openslxDB->changeVendorOS( + $vendorOS->{id}, + { 'clone_source' => $self->{'clone-source'} } + ); + vlog( + 0, + _tr( + "Vendor-OS '%s' has been updated in OpenSLX-database.\n", + $vendorOSName + ) + ); + } + else { + vlog( + 0, + _tr( + "No need to change vendor-OS '%s' in OpenSLX-database.\n", + $vendorOSName + ) + ); + } + # fetch installed plugins of this vendor-OS in order to reinstall them + @plugins = $openslxDB->fetchInstalledPlugins($vendorOS->{id}); + } + else { + my $data = { 'name' => $vendorOSName }; + if (length($self->{'clone-source'})) { + $data->{'clone_source'} = $self->{'clone-source'}; + } + my $id = $openslxDB->addVendorOS($data); + + vlog( + 0, + _tr( + "Vendor-OS '%s' has been added to DB (ID=%s).\n", + $vendorOSName, $id + ) + ); + # fetch plugins from default vendor-OS in order to install those into + # this new one + @plugins = $openslxDB->fetchInstalledPlugins(0); + } + + $openslxDB->disconnect(); + + # now that we have the list of plugins, we (re-)install all of them: + $self->_installPlugins(\@plugins, defined $vendorOS); + + return; +} + +sub removeVendorOSFromConfigDB +{ + my $self = shift; + + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + + my $vendorOSName = $self->{'vendor-os-name'}; + my $vendorOS = $openslxDB->fetchVendorOSByFilter({'name' => $vendorOSName}); + if (!defined $vendorOS) { + vlog( + 0, + _tr( + "Vendor-OS '%s' didn't exist in OpenSLX-database.\n", + $vendorOSName + ) + ); + } + else { + # remove all exports (and systems) using this vendor-OS and then + # remove the vendor-OS itself: + my @exports = $openslxDB->fetchExportByFilter( + {'vendor_os_id' => $vendorOS->{id}}); + foreach my $export (@exports) { + my $osExportEngine = instantiateClass("OpenSLX::OSExport::Engine"); + $osExportEngine->initializeFromExisting($export->{name}); + vlog( + 0, + _tr( + "purging export '%s', since it belongs to the vendor-OS " . + "being deleted...", + $export->{name} + ) + ); + $osExportEngine->purgeExport(); + } + + $openslxDB->removeVendorOS($vendorOS->{id}); + vlog( + 0, + _tr("Vendor-OS '%s' has been removed from DB!\n", $vendorOSName) + ); + } + + $openslxDB->disconnect(); + return; +} + +sub pickKernelFile +{ + my $self = shift; + + return $self->{distro}->pickKernelFile(@_); +} + +sub distroName +{ + my $self = shift; + + return $self->{'distro-name'}; +} + +sub metaPackager +{ + my $self = shift; + + return $self->{'meta-packager'}; +} + +sub packager +{ + my $self = shift; + + return $self->{'packager'}; +} + +sub getInstallablePackagesForSelection +{ + my $self = shift; + my $selKey = shift; + + return if !$selKey; + + my $selection = $self->{'distro-info'}->{selection}->{$selKey}; + return if !$selection; + + my @pkgs = split m{\s+}, $selection->{packages}; + my %installedPkgs; + @installedPkgs{ $self->{'packager'}->getInstalledPackages() } = (); + @pkgs = grep { !exists $installedPkgs{$_} } @pkgs; + + return join ' ', @pkgs; +} + +sub busyboxBinary +{ + my $self = shift; + + my $uclibdir = "$openslxConfig{'base-path'}/share/uclib-rootfs"; + + return sprintf( + "LD_LIBRARY_PATH=%s/lib %s/bin/busybox", + $uclibdir, + $uclibdir + ); +} + +################################################################################ +### implementation methods +################################################################################ +sub _readDistroInfo +{ + my $self = shift; + my $setupMirrorsIfNecessary = shift || 0; + + vlog(1, "reading configuration info for $self->{'vendor-os-name'}..."); + + $self->{'distro-info'} = { + 'package-subdir' => '', + 'prereq-packages' => '', + 'bootstrap-packages' => '', + 'metapackager' => {}, + 'repository' => {}, + 'selection' => {}, + 'excludes' => {}, + }; + + # merge user-provided configuration with distro defaults + foreach my $file ( + "$self->{'shared-distro-info-dir'}/settings.default", + "$self->{'config-distro-info-dir'}/settings" + ) { + if (-e $file) { + vlog(2, "reading configuration file $file..."); + my $configObject = Config::General->new( + -AllowMultiOptions => 0, + -AutoTrue => 1, + -ConfigFile => $file, + -LowerCaseNames => 1, + -SplitPolicy => 'equalsign', + ); + my %config = $configObject->getall(); + mergeHash($self->{'distro-info'}, \%config); + } + } + + # fetch mirrors for all repositories (if requested): + foreach my $repoKey (keys %{$self->{'distro-info'}->{repository}}) { + my $repo = $self->{'distro-info'}->{repository}->{$repoKey}; + $repo->{key} = $repoKey; + # if there is local URL, only that is used, otherwise we fetch the + # configured mirrors: + if (!$repo->{'local-url'}) { + $repo->{urls} = $self->_fetchConfiguredMirrorsForRepository( + $repo, $setupMirrorsIfNecessary + ); + } + } + + # expand all selections: + my $seen = {}; + foreach my $selKey (keys %{$self->{'distro-info'}->{selection}}) { + $self->_expandSelection($selKey, $seen); + } + + # dump distro-info, if asked for: + if ($openslxConfig{'log-level'} >= 2) { + my $repository = $self->{'distro-info'}->{repository}; + foreach my $r (sort keys %$repository) { + vlog(2, "repository '$r':"); + foreach my $k (sort keys %{$repository->{$r}}) { + vlog(3, "\t$k = '$repository->{$r}->{$k}'"); + } + } + my $selection = $self->{'distro-info'}->{selection}; + foreach my $s (sort keys %$selection) { + vlog(2, "selection '$s':"); + foreach my $k (sort keys %{$selection->{$s}}) { + vlog(3, "\t$k = '$selection->{$s}->{$k}'"); + } + } + my $excludes = $self->{'distro-info'}->{excludes}; + foreach my $e (sort keys %$excludes) { + vlog(2, "excludes for '$e':"); + foreach my $k (sort keys %{$excludes->{$e}}) { + vlog(3, "\t$k = '$excludes->{$e}->{$k}'"); + } + } + } + return; +} + +sub _fetchConfiguredMirrorsForRepository +{ + my $self = shift; + my $repoInfo = shift; + my $setupMirrorsIfNecessary = shift; + + my $configuredMirrorsFile + = "$self->{'config-distro-info-dir'}/mirrors/$repoInfo->{key}"; + if (!-e $configuredMirrorsFile) { + return '' if !$setupMirrorsIfNecessary; + vlog(0, + _tr( + "repo '%s' has no configured mirrors, let's pick some ...", + $repoInfo->{name} + ) + ); + $self->_configureBestMirrorsForRepository($repoInfo); + } + vlog(2, "reading configured mirrors file '$configuredMirrorsFile'."); + my $configObject = Config::General->new( + -AllowMultiOptions => 0, + -AutoTrue => 1, + -ConfigFile => $configuredMirrorsFile, + -LowerCaseNames => 1, + -SplitPolicy => 'equalsign', + ); + my %config = $configObject->getall(); + + return $config{urls}; +} + +sub _configureBestMirrorsForRepository +{ + my $self = shift; + my $repoInfo = shift; + + my $configuredMirrorsFile + = "$self->{'config-distro-info-dir'}/mirrors/$repoInfo->{key}"; + + if (!-e "$self->{'config-distro-info-dir'}/mirrors") { + mkdir "$self->{'config-distro-info-dir'}/mirrors"; + } + + my $allMirrorsFile + = "$self->{'shared-distro-info-dir'}/mirrors/$repoInfo->{key}"; + my @allMirrors = string2Array(scalar slurpFile($allMirrorsFile)); + + my $mirrorsToTryCount = $openslxConfig{'mirrors-to-try-count'} || 20; + my $mirrorsToUseCount = $openslxConfig{'mirrors-to-use-count'} || 5; + vlog(1, + _tr( + "selecting the '%s' best mirrors (from a set of '%s') for repo " . + "'%s' ...", + $mirrorsToUseCount, $mirrorsToTryCount, $repoInfo->{key} + ) + ); + + # determine own top-level domain: + my $topLevelDomain; + if (defined $openslxConfig{'mirrors-preferred-top-level-domain'}) { + $topLevelDomain + = lc($openslxConfig{'mirrors-preferred-top-level-domain'}); + } + else { + my $FQDN = getFQDN(); + $FQDN =~ m{\.(\w+)$}; + $topLevelDomain = lc($1); + } + + # select up to $mirrorsToTryCount "close" mirrors from the array ... + my @tryMirrors + = grep { + my $uri = URI->new($_); + my $host = $uri->host(); + $host =~ m{\.(\w+)$} && lc($1) eq $topLevelDomain; + } + @allMirrors; + + my $tryList = join("\n\t", @tryMirrors); + vlog(1, + _tr( + "mirrors matching the preferred top level domain ('%s'):\n\t%s\n", + $topLevelDomain, $tryList + ) + ); + + if (@tryMirrors > $mirrorsToTryCount) { + # shrink array to $mirrorsToTryCount elements + vlog(1, _tr("shrinking list to %s mirrors\n", $mirrorsToTryCount)); + $#tryMirrors = $mirrorsToTryCount; + } + elsif (@tryMirrors < $mirrorsToTryCount) { + # we need more mirrors, try adding some others randomly: + vlog(1, + _tr( + "filling list with %s more random mirrors:\n", + $mirrorsToTryCount - @tryMirrors + ) + ); + + # fill @untriedMirrors with the mirrors not already contained + # in @tryMirrors ... + my @untriedMirrors + = grep { + my $mirror = $_; + !grep { $mirror eq $_ } @tryMirrors; + } @allMirrors; + + # ... and pick randomly until we have reached the limit or there are + # no more unused mirrors left + foreach my $count (@tryMirrors..$mirrorsToTryCount-1) { + last if !@untriedMirrors; + my $index = int(rand(scalar @untriedMirrors)); + my $randomMirror = splice(@untriedMirrors, $index, 1); + push @tryMirrors, $randomMirror; + vlog(1, "\t$randomMirror\n"); + } + } + + # just make sure we are not going to try/use more mirros than we have + # available + if ($mirrorsToTryCount > @tryMirrors) { + $mirrorsToTryCount = @tryMirrors; + } + if ($mirrorsToUseCount > $mirrorsToTryCount) { + $mirrorsToUseCount = $mirrorsToTryCount; + } + + # ... fetch a file from all of these mirrors and measure the time taken ... + vlog(0, + _tr( + "testing %s mirrors to determine the fastest %s ...\n", + $mirrorsToTryCount, $mirrorsToUseCount + ) + ); + my %mirrorSpeed; + my $veryGoodSpeedCount = 0; + foreach my $mirror (@tryMirrors) { + if ($veryGoodSpeedCount >= $mirrorsToUseCount) { + # we already have enough mirrors with very good speed, + # it makes no sense to test any others. We simply set the + # time of the remaining mirrors to some large value, so they + # won't get picked: + $mirrorSpeed{$mirror} = 10000; + next; + } + + # test the current mirror and record the result + my $time = $self->_speedTestMirror( + $mirror, $repoInfo->{'file-for-speedtest'} + ); + $mirrorSpeed{$mirror} = $time; + if ($time <= 1) { + $veryGoodSpeedCount++; + } + } + + # ... now select the best (fastest) $mirrorsToUseCount mirrors ... + my @bestMirrors + = ( + sort { + $mirrorSpeed{$a} <=> $mirrorSpeed{$b}; + } + @tryMirrors + )[0..$mirrorsToUseCount-1]; + + vlog(0, + _tr( + "picked these '%s' mirrors for repo '%s':\n\t%s\n", + $mirrorsToUseCount, $repoInfo->{name}, join("\n\t", @bestMirrors) + ) + ); + + # ... and write them into the configuration file: + my $configObject = Config::General->new( + -AllowMultiOptions => 0, + -AutoTrue => 1, + -LowerCaseNames => 1, + -SplitPolicy => 'equalsign', + ); + $configObject->save_file($configuredMirrorsFile, { + 'urls' => join("\n", @bestMirrors), + }); + return; +} + +sub _speedTestMirror +{ + my $self = shift; + my $mirror = shift; + my $file = shift; + + vlog(0, _tr("\ttesting mirror '%s' ...\n", $mirror)); + + # do an explicit DNS-lookup as we do not want to include the time that takes + # in the speedtest + my $uri = URI->new($mirror); + my $hostName = $uri->host(); + if (!gethostbyname($hostName)) { + # unable to resolve host, we pretend it took really long + return 10000; + } + + # now measure the time it takes to download the file + my $wgetCmd = $self->busyboxBinary(); + $wgetCmd .= " wget -q -O - $mirror/$file >/dev/null"; + my $start = time(); + if (slxsystem($wgetCmd)) { + # just return any large number that is unlikely to be selected + return 10000; + } + my $time = time() - $start; + vlog(0, "\tfetched '$file' in $time seconds\n"); + return $time; +} + +sub _expandSelection +{ + my $self = shift; + my $selKey = shift; + my $seen = shift; + + return if $seen->{$selKey}; + $seen->{$selKey} = 1; + + return if !exists $self->{'distro-info'}->{selection}->{$selKey}; + my $selection = $self->{'distro-info'}->{selection}->{$selKey}; + + if ($selection->{base}) { + # add all packages from base selection(s) to the current one: + my $basePackages = ''; + for my $base (split ',', $selection->{base}) { + my $baseSelection = $self->{'distro-info'}->{selection}->{$base} + or die _tr( + 'base-selection "%s" is unknown (referenced in "%s")!', + $base, $selKey + ); + $self->_expandSelection($base, $seen); + $basePackages .= $baseSelection->{packages} || ''; + } + my $packages = $selection->{packages} || ''; + $selection->{packages} = $basePackages . "\n" . $packages; + } + return; +} + +sub _applyVendorOSSettings +{ + my $self = shift; + my $vendorOSSettings = shift; + + if (exists $vendorOSSettings->{'root-password'}) { + # hashes password according to requirements of current distro and + # writes it to /etc/shadow + $self->{distro}->setPasswordForUser( + 'root', $vendorOSSettings->{'root-password'} + ); + } + + return; +} + +sub _createVendorOSPath +{ + my $self = shift; + + if (slxsystem("mkdir -p $self->{'vendor-os-path'}")) { + die _tr("unable to create directory '%s', giving up! (%s)\n", + $self->{'vendor-os-path'}, $!); + } + return; +} + +sub _touchVendorOS +{ + my $self = shift; + + # touch root folder, as we are using this folder to determine the + # 'age' of the vendor-OS when trying to determine whether or not we + # need to re-export this vendor-OS: + slxsystem("touch $self->{'vendor-os-path'}"); + return; +} + +sub _generateDefaultDirs +{ + my $self = shift; + my $targetRoot = shift || $self->{'vendor-os-path'}; + + vlog(0, _tr("Creating default directories ...\n")); + + my $OPENSLX_DEFAULT_DIR = "/opt/openslx"; + my $OPENSLX_DEFAULT_CONFDIR = "/etc/opt/openslx"; + my $OPENSLX_DEFAULT_LOGDIR = "/var/log/openslx"; + my $OPENSLX_DEFAULT_VARDIR = "/var/opt/openslx"; + my $OPENSLX_DEFAULT_BINDIR = "$OPENSLX_DEFAULT_VARDIR/bin"; + my $OPENSLX_DEFAULT_LIBDIR = "$OPENSLX_DEFAULT_VARDIR/lib"; + my $OPENSLX_DEFAULT_VIRTDIR = "/var/lib/virt"; + mkpath("$targetRoot/$OPENSLX_DEFAULT_DIR", 0, 0755); + mkpath("$targetRoot/$OPENSLX_DEFAULT_CONFDIR", 0, 0755); + mkpath("$targetRoot/$OPENSLX_DEFAULT_LOGDIR", 0, 0755); + mkpath("$targetRoot/$OPENSLX_DEFAULT_BINDIR", 0, 0755); + mkpath("$targetRoot/$OPENSLX_DEFAULT_LIBDIR", 0, 0755); + mkpath("$targetRoot/$OPENSLX_DEFAULT_VIRTDIR", 0, 0755); + #system("chmod 0755 $targetRoot/$OPENSLX_DEFAULT_DIR"); + + my $openslxConfig = "# Default OpenSLX directories defined by satge 1\n"; + $openslxConfig .= "# Version 0.2\n\n"; + $openslxConfig .= "OPENSLX_DEFAULT_DIR=$OPENSLX_DEFAULT_DIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_CONFDIR=$OPENSLX_DEFAULT_CONFDIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_LOGDIR=$OPENSLX_DEFAULT_LOGDIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_VARDIR=$OPENSLX_DEFAULT_VARDIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_BINDIR=$OPENSLX_DEFAULT_BINDIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_LIBDIR=$OPENSLX_DEFAULT_LIBDIR\n"; + $openslxConfig .= "OPENSLX_DEFAULT_VIRTDIR=$OPENSLX_DEFAULT_VIRTDIR\n"; + + spitFile("$targetRoot/$OPENSLX_DEFAULT_CONFDIR/openslx.conf", + "$openslxConfig"); + + # add BINDIR to PATH + my $openslxDefaultPath = "PATH=$OPENSLX_DEFAULT_BINDIR:\$PATH\n"; + $openslxDefaultPath .= "export PATH\n"; + spitFile("$targetRoot/etc/profile.d/openslx-binpath.sh", + "$openslxDefaultPath"); +} + +sub _copyUclibcRootfs +{ + my $self = shift; + my $targetRoot = shift || $self->{'vendor-os-path'}; + my $distro = $self->{distro}; + + vlog(0, _tr("copying uclibc-rootfs into vendor-OS ...\n")); + + my $target = "$targetRoot/opt/openslx/uclib-rootfs"; + + if (system("mkdir -p $target")) { + die _tr("unable to create directory '%s', giving up! (%s)\n", + $target, $!); + } + + my $uclibcRootfs = "$openslxConfig{'base-path'}/share/uclib-rootfs"; + my @excludes = qw( + dialog + kexec + libcurses.so* + libncurses.so* + ); + my $exclOpts = join ' ', map { "--exclude $_" } @excludes; + vlog(3, _tr("using exclude-filter:\n%s\n", $exclOpts)); + my $rsyncFH; + my $rsyncCmd + = "rsync -aq --delete-excluded --exclude-from=- $uclibcRootfs/ $target"; + vlog(2, "executing: $rsyncCmd\n"); + # if we're doing a fresh install we need to create /lib, /bin first + mkdir "$targetRoot/lib"; + mkdir "$targetRoot/bin"; + + open($rsyncFH, '|-', $rsyncCmd) + or die _tr("unable to start rsync for source '%s', giving up! (%s)", + $uclibcRootfs, $!); + print $rsyncFH $exclOpts; + close($rsyncFH) + or die _tr("unable to copy to target '%s', giving up! (%s)", + $target, $!); + + # write version of uclibc-rootfs original into a file in order to be + # able to check the up-to-date state later (in the config-demuxer) + slxsystem("slxversion >${target}.version"); + + return; +} + +sub _createPackager +{ + my $self = shift; + + my $packagerClass + = "OpenSLX::OSSetup::Packager::$self->{distro}->{'packager-type'}"; + my $packager = instantiateClass($packagerClass); + $packager->initialize($self); + $self->{'packager'} = $packager; + return; +} + +sub _createMetaPackager +{ + my $self = shift; + + my $metaPackagerType = $self->{distro}->{'meta-packager-type'}; + + my $installInfoFile = "$self->{'vendor-os-path'}/.openslx-install-info"; + if (-e $installInfoFile) { + # activate the meta-packager that was used when installing the os: + my $installInfo = slurpFile($installInfoFile); + if ($installInfo =~ m[SLX_META_PACKAGER=(\w+)]) { + $metaPackagerType = $1; + } + } + + my $metaPackagerClass = "OpenSLX::OSSetup::MetaPackager::$metaPackagerType"; + my $metaPackager = instantiateClass($metaPackagerClass); + $metaPackager->initialize($self); + $self->{'meta-packager'} = $metaPackager; + return; +} + +sub _sortRepositoryURLs +{ + my $self = shift; + my $repoInfo = shift; + + my @URLs + = defined $repoInfo->{'local-url'} + ? $repoInfo->{'local-url'} + : string2Array($repoInfo->{urls}); + if (!@URLs) { + die( + _tr( + "repository '%s' has no URLs defined, " . + "unable to fetch anything!", + $repoInfo->{name}, + ) + ); + } + + return \@URLs; +} + +sub _downloadBaseFiles +{ + my $self = shift; + my $files = shift; + use vars qw(@filelisting); + + my $pkgSubdir = $self->{'distro-info'}->{'package-subdir'}; + my @URLs = @{$self->{'baseURLs'}}; + my $maxTryCount = $openslxConfig{'ossetup-max-try-count'}; + my @possiblefiles; + + my @foundFiles; + foreach my $fileVariantStr (@$files) { + my $tryCount = 0; + next unless $fileVariantStr =~ m[\S]; + my $foundFile; +try_next_url: + my $url = $URLs[$self->{'baseURL-index'}]; + $url .= "/$pkgSubdir" if length($pkgSubdir); + + foreach my $file (split '\s+', $fileVariantStr) { + #substitute given name with real filename including version number + my $basefile = basename($file); + my $basedir = dirname($file)."/"; + @possiblefiles = grep(/^$basefile/,@filelisting); + #selecting always the first occurence + if ($possiblefiles[0]) { + $basefile = $possiblefiles[0]; + } elsif ($basefile =~ /.*\.rpm/) { + vlog(5,"Trying suggested name because of .rpm-ending."); + } else { + die _tr("file <$basefile> not found in list received from" . + "mirror"); + } + vlog(2, "fetching <$basefile>..."); + if (slxsystem("wget", "-c", "-O", "$basefile", + "$url/$basedir$basefile") == 0) { + $foundFile = $basefile; + last; + } + elsif (-e $basefile) { + vlog(0, "removing left-over '$basefile' and trying again..."); + unlink $basefile; + redo; + } + } + if (!defined $foundFile) { + if ($tryCount < $maxTryCount) { + $tryCount++; + $self->{'baseURL-index'} + = ($self->{'baseURL-index'} + 1) % scalar(@URLs); + vlog( + 0, + _tr( + "switching to mirror '%s'.", + $URLs[$self->{'baseURL-index'}] + ) + ); + goto try_next_url; + } + die _tr("unable to fetch '%s' from any source!\n", $fileVariantStr); + } + push @foundFiles, $foundFile; + } + return @foundFiles; +} + +sub _startLocalURLServersAsNeeded +{ + my $self = shift; + + my $port = 5080; + my %portForURL; + foreach my $repoInfo (values %{$self->{'distro-info'}->{repository}}) { + my $localURL = $repoInfo->{'local-url'} || ''; + next if !$localURL; + next if $localURL =~ m[^\w+:]; # anything /w a protcol-spec is non-local + if (!exists $localHttpServers{$localURL}) { + my $pid + = executeInSubprocess( + $self->busyboxBinary(), "httpd", '-p', $port, '-h', '/', + '-f' + ); + vlog(1, + _tr( + "started local HTTP-server for URL '%s' on port '%s'.", + $localURL, $port + ) + ); + $repoInfo->{'local-url'} = "http://localhost:$port$localURL"; + $localHttpServers{$localURL}->{pid} = $pid; + $localHttpServers{$localURL}->{url} = $repoInfo->{'local-url'}; + $port++; + } + else { + $repoInfo->{'local-url'} = $localHttpServers{$localURL}->{url}; + } + } + return; +} + +sub _stopLocalURLServers +{ + my $self = shift; + + while (my ($localURL, $serverInfo) = each %localHttpServers) { + vlog(1, _tr("stopping local HTTP-server for URL '%s'.", $localURL)); + kill TERM => $serverInfo->{pid}; + } +} + +sub _setupStage1A +{ + my $self = shift; + + vlog(1, "setting up stage1a for $self->{'vendor-os-name'}..."); + + # specify individual paths for the respective substages: + $self->{stage1aDir} = "$self->{'vendor-os-path'}/stage1a"; + $self->{stage1bSubdir} = 'slxbootstrap'; + $self->{stage1cSubdir} = 'slxfinal'; + + # we create *all* of the above folders by creating stage1cDir: + my $stage1cDir + = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}/". + "$self->{'stage1cSubdir'}"; + if (slxsystem("mkdir -p $stage1cDir")) { + die _tr("unable to create directory '%s', giving up! (%s)\n", + $stage1cDir, $!); + } + + $self->_stage1A_setupUclibcEnvironment(); + $self->_stage1A_copyPrerequiredFiles(); + $self->_stage1A_copyTrustedPackageKeys(); + $self->_stage1A_createRequiredFiles(); + return; +} + +sub _stage1A_setupUclibcEnvironment +{ + my $self = shift; + $self->_copyUclibcRootfs("$self->{stage1aDir}/$self->{stage1bSubdir}"); + my $source = "$self->{stage1bSubdir}/opt/openslx/uclib-rootfs"; + my $target = "$self->{stage1aDir}"; + slxsystem("ln -sf $source/bin $target/bin"); + slxsystem("ln -sf $source/lib $target/lib"); + slxsystem("ln -sf $source/usr $target/usr"); + $self->_stage1A_setupResolver(); + + return; +} + + +sub _stage1A_setupResolver +{ + my $self = shift; + my $libcFolder = shift; + + #if (!defined $libcFolder) { + # warn _tr("unable to determine libc-target-folder, will use /lib!"); + # $libcFolder = '/lib'; + #} + + copyFile('/etc/resolv.conf', "$self->{stage1aDir}/etc"); + copyFile('/etc/nsswitch.conf', "$self->{stage1aDir}/etc"); + spitFile("$self->{stage1aDir}/etc/hosts", "127.0.0.1 localhost\n"); + #copyFile("$libcFolder/libresolv*", "$self->{stage1aDir}$libcFolder"); + #copyFile("$libcFolder/libnss_dns*", "$self->{stage1aDir}$libcFolder"); + #copyFile("$libcFolder/libnss_files*", "$self->{stage1aDir}$libcFolder"); + + my $stage1cDir + = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}/" . + "$self->{'stage1cSubdir'}"; + copyFile('/etc/resolv.conf', "$stage1cDir/etc"); + return; +} + +sub _stage1A_copyPrerequiredFiles +{ + my $self = shift; + + return unless -d "$self->{'shared-distro-info-dir'}/prereqfiles"; + + vlog(2, "copying folder with pre-required files..."); + my $stage1cDir + = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}/" . + "$self->{'stage1cSubdir'}"; + my $cmd = qq[ + tar -cp -C $self->{'shared-distro-info-dir'}/prereqfiles . \\ + | tar -xp -C $stage1cDir + ]; + if (slxsystem($cmd)) { + die _tr( + "unable to copy folder with pre-required files to folder '%s'" . + "(%s)\n", + $stage1cDir, $! + ); + } + vlog(2, "fix pre-required files..."); + $self->{distro}->fixPrerequiredFiles($stage1cDir); + return; +} + +sub _stage1A_copyTrustedPackageKeys +{ + my $self = shift; + + vlog(2, "copying folder with trusted package keys..."); + my $stage1bDir = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}"; + foreach my $folder ( + $self->{'shared-distro-info-dir'}, $self->{'config-distro-info-dir'} + ) { + next unless -d "$folder/trusted-package-keys"; + my $cmd = qq[ + tar -cp -C $folder trusted-package-keys \\ + | tar -xp -C $stage1bDir + ]; + if (slxsystem($cmd)) { + die _tr( + "unable to copy folder with trusted package keys to folder " . + "'%s' (%s)\n", + "$stage1bDir/trusted-package-keys", $! + ); + } + slxsystem("chmod 444 $stage1bDir/trusted-package-keys/*"); + + # install ultimately trusted keys (from distributor): + my $stage1cDir = "$stage1bDir/$self->{'stage1cSubdir'}"; + my $keyDir = "$self->{'shared-distro-info-dir'}/trusted-package-keys"; + if (-e "$keyDir/pubring.gpg") { + copyFile("$keyDir/pubring.gpg", "$stage1cDir/usr/lib/rpm/gnupg"); + } + } + return; +} + +sub _stage1A_createRequiredFiles +{ + my $self = shift; + + vlog(2, "creating required files..."); + + # fake all files required by stage1b (by creating them empty): + my $stage1bDir = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}"; + foreach my $fake (@{$self->{distro}->{'stage1b-faked-files'}}) { + fakeFile("$stage1bDir/$fake"); + } + + # fake all files required by stage1c (by creating them empty): + my $stage1cDir = "$stage1bDir/$self->{'stage1cSubdir'}"; + foreach my $fake (@{$self->{distro}->{'stage1c-faked-files'}}) { + fakeFile("$stage1cDir/$fake"); + } + + mkdir "$stage1cDir/dev"; + if (!-e "$stage1cDir/dev/null" + && slxsystem("mknod $stage1cDir/dev/null c 1 3")) + { + die _tr( + "unable to create node '%s' (%s)\n", "$stage1cDir/dev/null", $! + ); + } + return; +} + +sub _setupStage1B +{ + my $self = shift; + + vlog(1, "setting up stage1b for $self->{'vendor-os-name'}..."); + $self->_stage1B_chrootAndBootstrap(); + return; +} + +sub _stage1B_chrootAndBootstrap +{ + my $self = shift; + + # give packager a chance to copy required files into stage1a-folder: + $self->{packager}->prepareBootstrap($self->{stage1aDir}); + + $self->_callChrootedFunction({ + chrootDir => $self->{stage1aDir}, + function => sub { + # chdir into slxbootstrap, as we want to drop packages into there: + chdir "/$self->{stage1bSubdir}" + or die _tr( + "unable to chdir into '%s' (%s)\n", + "/$self->{stage1bSubdir}", $! + ); + + # fetch prerequired packages and use them to bootstrap the packager: + $self->{'baseURLs'} = $self->_sortRepositoryURLs( + $self->{'distro-info'}->{repository}->{base} + ); + $self->{'baseURL-index'} = 0; + my @pkgs = + string2Array($self->{'distro-info'}->{'prereq-packages'}); + vlog( + 2, + "downloading these prereq packages:\n\t" . join("\n\t", @pkgs) + ); + my @prereqPkgs = $self->_downloadBaseFiles(\@pkgs); + $self->{'prereq-packages'} = \@prereqPkgs; + $self->{packager}->bootstrap(\@prereqPkgs); + + @pkgs = + string2Array($self->{'distro-info'}->{'bootstrap-packages'}); + push( + @pkgs, + string2Array( + $self->{'distro-info'}->{'metapackager'} + ->{$self->{distro}->{'meta-packager-type'}}->{packages} + ) + ); + vlog( + 2, + "downloading bootstrap packages:\n\t" . join("\n\t", @pkgs) + ); + my @bootstrapPkgs = $self->_downloadBaseFiles(\@pkgs); + $self->{'bootstrap-packages'} = \@bootstrapPkgs; + }, + }); + return; +} + +sub _setupStage1C +{ + my $self = shift; + + vlog(1, "setting up stage1c for $self->{'vendor-os-name'}..."); + $self->_stage1C_chrootAndInstallBasicVendorOS(); + return; +} + +sub _stage1C_chrootAndInstallBasicVendorOS +{ + my $self = shift; + + my $stage1bDir = "/$self->{stage1bSubdir}"; + chrootInto($stage1bDir); + + my $stage1cDir = "/$self->{stage1cSubdir}"; + + # import any additional trusted package keys to rpm-DB: + my $keyDir = "/trusted-package-keys"; + my $keyDirDH; + if (opendir($keyDirDH, $keyDir)) { + my @keyFiles + = map { "$keyDir/$_" } + grep { $_ !~ m[^(\.\.?|pubring.gpg)$] } + readdir($keyDirDH); + closedir($keyDirDH); + $self->{packager}->importTrustedPackageKeys(\@keyFiles, $stage1cDir); + } + + # install bootstrap packages + $self->{packager}->installPackages( + $self->{'bootstrap-packages'}, $stage1cDir + ); + return; +} + +sub _stage1C_cleanupBasicVendorOS +{ + my $self = shift; + + my $stage1cDir + = "$self->{'stage1aDir'}/$self->{'stage1bSubdir'}/" . + "$self->{'stage1cSubdir'}"; + if (slxsystem("mv $stage1cDir/* $self->{'vendor-os-path'}/")) { + die _tr( + "unable to move final setup to '%s' (%s)\n", + $self->{'vendor-os-path'}, $! + ); + } + if (slxsystem("rm -rf $self->{stage1aDir}")) { + die _tr( + "unable to remove temporary folder '%s' (%s)\n", + $self->{stage1aDir}, $! + ); + } + return; +} + +sub _setupStage1D +{ + my $self = shift; + + vlog(1, "setting up stage1d for $self->{'vendor-os-name'}..."); + + $self->_callChrootedFunction({ + chrootDir => $self->{'vendor-os-path'}, + function => sub { + $self->_stage1D_setupPackageSources(); + $self->_stage1D_updateBasicVendorOS(); + $self->{distro}->preSystemInstallationHook(); + my $ok = eval { + $self->_stage1D_installPackageSelection(); + 1; + }; + my $err = $ok ? undef : $@; + $self->{distro}->postSystemInstallationHook(); + die $err if defined $err; + }, + updateConfig => 1, + }); + return; +} + +sub _updateStage1D +{ + my $self = shift; + + vlog(1, "updating $self->{'vendor-os-name'}..."); + + $self->_callChrootedFunction({ + chrootDir => $self->{'vendor-os-path'}, + function => sub { + $self->_stage1D_updateBasicVendorOS(); + }, + updateConfig => 1, + }); + return; +} + +sub _startChrootedShellInStage1D +{ + my $self = shift; + + vlog(0, "starting chrooted shell for $self->{'vendor-os-name'}"); + vlog(0, "---------------------------------------"); + vlog(0, "- please type 'exit' if you are done! -"); + vlog(0, "---------------------------------------"); + + $self->_callChrootedFunction({ + chrootDir => $self->{'vendor-os-path'}, + function => sub { + # will hang until user exits manually: + slxsystem($openslxConfig{'default-shell'}); + }, + updateConfig => 1, + }); + return; +} + +sub _callChrootedFunction +{ + my $self = shift; + my $params = shift; + + checkParams($params, { + 'chrootDir' => '!', + 'function' => '!', + 'updateConfig' => '?', + }); + + my $distro = $self->{distro}; + my $distroSession = OpenSLX::ScopedResource->new({ + name => 'ossetup::distro::session', + acquire => sub { $distro->startSession($params->{chrootDir}); 1 }, + release => sub { $distro->finishSession(); 1 }, + }); + + die $@ if ! eval { + # invoke given function: + $params->{function}->(); + $distro->updateDistroConfig() if $params->{updateConfig}; + 1; + }; + + return; +} + +sub _stage1D_setupPackageSources +{ + my $self = shift; + + vlog(1, "setting up package sources for meta packager..."); + my $selectionName = $self->{'selection-name'}; + my $pkgExcludes + = $self->{'distro-info'}->{excludes}->{$selectionName}->{packages}; + my $excludeList = join ' ', string2Array($pkgExcludes); + $self->{'meta-packager'}->initPackageSources(); + my ($rk, $repo); + while (($rk, $repo) = each %{$self->{'distro-info'}->{repository}}) { + vlog(2, "setting up package source $rk..."); + $self->{'meta-packager'}->setupPackageSource( + $rk, $repo, $excludeList, $self->_sortRepositoryURLs($repo) + ); + } + return; +} + +sub _stage1D_updateBasicVendorOS +{ + my $self = shift; + + vlog(1, "updating basic vendor-os..."); + $self->{'meta-packager'}->updateBasicVendorOS(); + return; +} + +sub _stage1D_installPackageSelection +{ + my $self = shift; + + my $selectionName = $self->{'selection-name'}; + + vlog(1, "installing package selection <$selectionName>..."); + my $selection = $self->{'distro-info'}->{selection}->{$selectionName}; + my @pkgs = string2Array($selection->{packages}); + my @installedPkgs = $self->{'packager'}->getInstalledPackages(); + @pkgs = grep { + my $pkg = $_; + if (grep { $_ eq $pkg; } @installedPkgs) { + vlog(1, "package '$pkg' filtered, it is already installed."); + 0; + } + else { + 1; + } + } @pkgs; + if (!@pkgs) { + vlog( + 0, + _tr( + "No packages listed for selection '%s', nothing to do.", + $selectionName + ) + ); + } + else { + vlog(1, "installing these packages:\n" . join("\n\t", @pkgs)); + $self->{'meta-packager'}->installPackages(join(' ', @pkgs), 1); + } + return; +} + +sub _clone_fetchSource +{ + my $self = shift; + my $source = shift; + + vlog( + 0, + _tr( + "Cloning vendor-OS from '%s' to '%s'...\n", $source, + $self->{'vendor-os-path'} + ) + ); + my $excludeIncludeList = $self->_clone_determineIncludeExcludeList(); + vlog(1, "using exclude-include-filter:\n$excludeIncludeList\n"); + my $additionalRsyncOptions = $ENV{SLX_RSYNC_OPTIONS} || ''; + my $rsyncCmd + = "rsync -av --delete --exclude-from=- $additionalRsyncOptions" + . " $source $self->{'vendor-os-path'}"; + vlog(2, "executing: $rsyncCmd\n"); + my $rsyncFH; + open($rsyncFH, '|-', $rsyncCmd) + or croak( + _tr( + "unable to start rsync for source '%s', giving up! (%s)\n", + $source, $! + ) + ); + print $rsyncFH $excludeIncludeList; + if (!close($rsyncFH)) { + print "rsync-result=", 0+$!, "\n"; + croak _tr( + "unable to clone from source '%s', giving up! (%s)\n", $source, $! + ); + } + return; +} + +sub _clone_determineIncludeExcludeList +{ + my $self = shift; + + my $localFilterFile + = "$openslxConfig{'config-path'}/distro-info/clone-filter"; + my $includeExcludeList + = slurpFile($localFilterFile, { failIfMissing => 0 }); + $includeExcludeList .= $self->{distro}->{'clone-filter'}; + $includeExcludeList =~ s[^\s+][]igms; + + # remove any leading whitespace, as rsync doesn't like it + return $includeExcludeList; +} + +sub _installPlugins +{ + my $self = shift; + my $plugins = shift; + my $isReInstall = shift; + + if (!$plugins) { + $plugins = []; + my $openslxDB = instantiateClass("OpenSLX::ConfigDB"); + $openslxDB->connect(); + # fetch plugins from existing vendor-OS + my $vendorOS = $openslxDB->fetchVendorOSByFilter({ + 'name' => $self->{'vendor-os-name'} + }); + if ($vendorOS) { + push @$plugins, $openslxDB->fetchInstalledPlugins($vendorOS->{id}); + $isReInstall = 1; + } + $openslxDB->disconnect(); + } + + return if ! @$plugins; + + require OpenSLX::OSPlugin::Engine; + vlog( + 0, + $isReInstall + ? _tr("reinstalling plugins...\n") + : _tr("installing default plugins...\n") + ); + for my $pluginInfo ( + sort { + $self->_sortPluginsByDependency($a->{plugin_name}, + $b->{plugin_name}); + } @$plugins + ) { + my $pluginName = $pluginInfo->{plugin_name}; + my $pluginEngine = OpenSLX::OSPlugin::Engine->new(); + vlog(0, _tr("\t%s\n", $pluginName)); + $pluginEngine->initialize( + $pluginName, $self->{'vendor-os-name'}, $pluginInfo->{attrs} + ); + $pluginEngine->installPlugin(); + } + vlog(0, _tr("done with plugins.\n")); + + return; +} + +sub _sortPluginsByDependency +{ + my $self = shift; + my $pluginNameA = shift; + my $pluginNameB = shift; + + my $pluginA = OpenSLX::OSPlugin::Roster->getPlugin($pluginNameA); + if ($pluginA->dependsOnPlugin($pluginNameB)) { + return 1; + } + my $pluginB = OpenSLX::OSPlugin::Roster->getPlugin($pluginNameB); + if ($pluginB->dependsOnPlugin($pluginNameA)) { + return -1; + } + return 0; +} + +################################################################################ +### utility methods +################################################################################ +sub _changePersonalityIfNeeded +{ + my $self = shift; + + my $distroName = $self->{'distro-name'}; + if ($self->_hostIs64Bit() && $distroName !~ m[_64]) { + vlog(2, 'entering 32-bit personality'); + OpenSLX::Syscall->enter32BitPersonality(); + } + return; +} + +sub _hostIs64Bit +{ + my $self = shift; + + $self->{arch} = `uname -m` unless defined $self->{arch}; + return ($self->{arch} =~ m[64]); +} + +1; + +=pod + +=head1 NAME + +OpenSLX::OSSetup::Engine - driver engine for OSSetup API + +=head1 SYNOPSIS + +... + +=cut + diff --git a/src/installer/OpenSLX/OSSetup/MetaPackager/Base.pm b/src/installer/OpenSLX/OSSetup/MetaPackager/Base.pm new file mode 100644 index 00000000..f149d0f5 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/MetaPackager/Base.pm @@ -0,0 +1,98 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# Base.pm +# - provides empty base of the OpenSLX OSSetup::MetaPackager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::MetaPackager::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSSetup::MetaPackager::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between meta-packager and its engine + + return; +} + +sub initPackageSources +{ +} + +sub setupPackageSource +{ +} + +sub updateBasicVendorOS +{ +} + +sub installPackages +{ +} + +sub removePackages +{ +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSSetup::MetaPackager::Base - the base class for all OSSetup::MetaPackagers + +=head1 SYNOPSIS + + package OpenSLX::OSSetup::MetaPackager::coolnewpkg; + + use vars qw(@ISA $VERSION); + @ISA = ('OpenSLX::OSSetup::MetaPackager::Base'); + $VERSION = 1.01; + + use coolnewpkg; + + sub new + { + my $class = shift; + my $self = {}; + return bless $self, $class; + } + + # override all methods of OpenSLX::OSSetup::MetaPackager::Base in order to + # implement the support for a new meta-packager + ... + +I> + +=cut diff --git a/src/installer/OpenSLX/OSSetup/MetaPackager/apt.pm b/src/installer/OpenSLX/OSSetup/MetaPackager/apt.pm new file mode 100644 index 00000000..ecb87a35 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/MetaPackager/apt.pm @@ -0,0 +1,142 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# apt.pm +# - provides apt-get-specific overrides of the OpenSLX::OSSetup::MetaPackager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::MetaPackager::apt; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::MetaPackager::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'apt', + }; + return bless $self, $class; +} + +sub initPackageSources +{ + my $self = shift; + + $ENV{LC_ALL} = 'POSIX'; + + # remove any existing sources + slxsystem('rm -f /etc/apt/sources.list'); + + # create default timezone if there isn't any + if (!-e '/etc/timezone') { + spitFile('/etc/timezone', "$openslxConfig{'default-timezone'}\n"); + } + + # create kernel config if there isn't any + if (!-e '/etc/kernel-img.conf') { + my $kernelConfig = unshiftHereDoc(<<" END-OF-HERE"); + # Kernel image management overrides + # See kernel-img.conf(5) for details + do_symlinks = yes + relative_links = yes + do_bootloader = no + do_bootfloppy = no + do_initrd = yes + link_in_boot = yes + END-OF-HERE + spitFile('/etc/kernel-img.conf', $kernelConfig); + } + + return 1; +} + +sub setupPackageSource +{ + my $self = shift; + my $repoName = shift; + my $repoInfo = shift; + my $excludeList = shift; + my $repoURLs = shift; + + my $baseURL = shift @$repoURLs; + my $distribution = $repoInfo->{'distribution'}; + my $components = $repoInfo->{'components'}; + + my $sourcesList = "deb $baseURL $distribution $components\n"; + + foreach my $mirrorURL (@$repoURLs) { + $sourcesList .= "deb $mirrorURL $distribution $components\n"; + } + + appendFile('/etc/apt/sources.list', $sourcesList); + + return; +} + +sub installPackages +{ + my $self = shift; + my $packages = shift; + my $doRefresh = shift || 0; + + $packages =~ tr{\n}{ }; + + if ($doRefresh && slxsystem("apt-get -y update")) { + die _tr("unable to update repository info (%s)\n", $!); + } + if ('/var/cache/debconf/slx-defaults.dat') { + $ENV{DEBCONF_DB_FALLBACK} + = "'File{/var/cache/debconf/slx-defaults.dat}'"; + } + $ENV{DEBIAN_FRONTEND} = 'noninteractive'; + if (slxsystem("apt-get -y install $packages")) { + die _tr("unable to install selection (%s)\n", $!); + } + delete $ENV{DEBCONF_DB_FALLBACK}; + delete $ENV{DEBIAN_FRONTEND}; + + return 1; +} + +sub removePackages +{ + my $self = shift; + my $pkgSelection = shift; + + if (slxsystem("apt-get -y remove $pkgSelection")) { + die _tr("unable to remove selection (%s)\n", $!); + } + + return 1; +} + +sub updateBasicVendorOS +{ + my $self = shift; + + if (slxsystem("apt-get -y update")) { + die _tr("unable to update repository info (%s)\n", $!); + } + if (slxsystem("apt-get -y upgrade")) { + die _tr("unable to update this vendor-os (%s)\n", $!); + } + + return 1; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/MetaPackager/smart.pm b/src/installer/OpenSLX/OSSetup/MetaPackager/smart.pm new file mode 100644 index 00000000..fc178cb7 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/MetaPackager/smart.pm @@ -0,0 +1,127 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# smart.pm +# - provides smart-specific overrides of the OpenSLX::OSSetup::MetaPackager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::MetaPackager::smart; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::MetaPackager::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'smart', + }; + return bless $self, $class; +} + +sub initPackageSources +{ + my $self = shift; + + $ENV{LC_ALL} = 'POSIX'; + + # remove any existing channels + slxsystem("rm -f /etc/smart/channels/*"); + if (slxsystem("smart channel -y --remove-all")) { + die _tr("unable to remove existing channels (%s)\n", $!); + } + return 1; +} + +sub setupPackageSource +{ + my $self = shift; + my $repoName = shift; + my $repoInfo = shift; + my $excludeList = shift; + my $repoURLs = shift; + + my $repoSubdir = ''; + if ($repoInfo->{'repo-subdir'}) { + $repoSubdir = "/$repoInfo->{'repo-subdir'}"; + } + my $baseURL = shift @$repoURLs; + my $repoDescr + = qq[$repoName name="$repoInfo->{name}" baseurl=$baseURL$repoSubdir]; + $repoDescr .= " type=rpm-md"; + if (slxsystem("smart channel -y --add $repoDescr")) { + die _tr("unable to add channel '%s' (%s)\n", $repoName, $!); + } + + my $mirrorDescr; + foreach my $mirrorURL (@$repoURLs) { + $mirrorDescr .= " --add $baseURL$repoSubdir $mirrorURL$repoSubdir"; + } + if (defined $mirrorDescr) { + if (slxsystem("smart mirror $mirrorDescr")) { + die _tr( + "unable to add mirrors for channel '%s' (%s)\n", + $repoName, $! + ); + } + } + return 1; +} + +sub installPackages +{ + my $self = shift; + my $packages = shift; + my $doRefresh = shift || 0; + + $packages =~ tr{\n}{ }; + + if ($doRefresh && slxsystem("smart update")) { + die _tr("unable to update channel info (%s)\n", $!); + } + if (slxsystem("smart install -y $packages")) { + die _tr("unable to install selection (%s)\n", $!); + } + return 1; +} + +sub removePackages +{ + my $self = shift; + my $pkgSelection = shift; + + if (slxsystem("smart remove -y $pkgSelection")) { + die _tr("unable to remove selection (%s)\n", $!); + } + return 1; +} + +sub updateBasicVendorOS +{ + my $self = shift; + + if (slxsystem("smart upgrade -y --update")) { + if ($! == 2) { + # file not found => smart isn't installed + die _tr("unable to update this vendor-os, as it seems to lack an installation of smart!\n"); + } + die _tr("unable to update this vendor-os (%s)\n", $!); + } + return 1; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/MetaPackager/yum.pm b/src/installer/OpenSLX/OSSetup/MetaPackager/yum.pm new file mode 100644 index 00000000..99a10382 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/MetaPackager/yum.pm @@ -0,0 +1,117 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# yum.pm +# - provides yum-specific overrides of the OpenSLX::OSSetup::MetaPackager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::MetaPackager::yum; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::MetaPackager::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'yum', + }; + return bless $self, $class; +} + +sub initPackageSources +{ + my $self = shift; + + $ENV{LC_ALL} = 'POSIX'; + + slxsystem("rm -f /etc/yum.repos.d/*"); + slxsystem("mkdir -p /etc/yum.repos.d"); + + return 1; +} + +sub setupPackageSource +{ + my $self = shift; + my $repoName = shift; + my $repoInfo = shift; + my $excludeList = shift; + my $repoURLs = shift; + + my $repoSubdir; + if (length($repoInfo->{'repo-subdir'})) { + $repoSubdir = "/$repoInfo->{'repo-subdir'}"; + } + my $baseURL = shift @$repoURLs; + + my $repoDescr + = "[$repoName]\nname=$repoInfo->{name}\nbaseurl=$baseURL$repoSubdir\n"; + vlog(4,"Adding repo <",$repoName,"> with Base-URL <",$baseURL,"> and Repo-SubDir <",$repoSubdir,">"); + foreach my $mirrorURL (@$repoURLs) { + $repoDescr .= " $mirrorURL$repoSubdir\n"; + } + my $repoFile = "/etc/yum.repos.d/$repoName.repo"; + spitFile($repoFile, "$repoDescr\nexclude=$excludeList\n"); + + return 1; +} + +sub installPackages +{ + my $self = shift; + my $packages = shift; + + $packages =~ tr{\n}{ }; + if (slxsystem("mount -t proc proc proc/") != 0){die _tr("unable to mount proc/ for yum \n");}; + if (slxsystem("yum -y install $packages")) { + die _tr("unable to install selection (%s)\n", $!); + } + if(slxsystem("umount proc/") != 0) {_tr("unable to umount proc/")}; + + return 1; +} + +sub removePackages +{ + my $self = shift; + my $pkgSelection = shift; + + if (slxsystem("yum -y remove $pkgSelection")) { + die _tr("unable to remove selection (%s)\n", $!); + } + + return 1; +} + +sub updateBasicVendorOS +{ + my $self = shift; + if (slxsystem("mount -t proc proc proc/") != 0){die _tr("unable to mount proc/ for yum \n");}; + if (slxsystem("yum -y update")) { + if ($! == 2) { + # file not found => yum isn't installed + die _tr("unable to update this vendor-os, as it seems to lack an installation of yum!\n"); + } + if(slxsystem("umount proc/") != 0) {_tr("unable to umount proc/")}; + die _tr("unable to update this vendor-os (%s)\n", $!); + } + if(slxsystem("umount proc/") != 0) {_tr("unable to umount proc/")}; + return 1; +} + +1; \ No newline at end of file diff --git a/src/installer/OpenSLX/OSSetup/MetaPackager/zypper.pm b/src/installer/OpenSLX/OSSetup/MetaPackager/zypper.pm new file mode 100644 index 00000000..4bb22bde --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/MetaPackager/zypper.pm @@ -0,0 +1,122 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# zypper.pm +# - provides zypper-specific overrides of the OpenSLX::OSSetup::MetaPackager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::MetaPackager::zypper; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::MetaPackager::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'zypper', + }; + return bless $self, $class; +} + +sub initPackageSources +{ + my $self = shift; + + $ENV{LC_ALL} = 'POSIX'; + + # remove any existing channels + slxsystem("rm -f /etc/zypp/repos.d/*"); + + return 1; +} + +sub setupPackageSource +{ + my $self = shift; + my $repoName = shift; + my $repoInfo = shift; + my $excludeList = shift; + my $repoURLs = shift; + + my $repoSubdir = ''; + if (defined $repoInfo->{'repo-subdir'} && + length($repoInfo->{'repo-subdir'})) { + $repoSubdir = "/$repoInfo->{'repo-subdir'}"; + } + my $baseURL = shift @$repoURLs; + + if ($baseURL =~ m/non-oss/) { + # skip non-oss repositories, cause zypper can't realy handle them + # correctly; zypper is deacting them with following message: + # "Repository type can't be determined." + return 1; + } + + if (slxsystem("zypper addrepo $baseURL$repoSubdir $repoName")) { + die _tr("unable to add repo '%s' (%s)\n", $repoName, $!); + } + + return 1; +} + +sub installPackages +{ + my $self = shift; + my $packages = shift; + my $doRefresh = shift || 0; + + $packages =~ tr{\n}{ }; + + if ($doRefresh && slxsystem("zypper --non-interactive refresh")) { + die _tr("unable to update repo info (%s)\n", $!); + } + if (slxsystem("zypper --non-interactive install $packages")) { + die _tr("unable to install selection (%s)\n", $!); + } + + return 1; +} + +sub removePackages +{ + my $self = shift; + my $pkgSelection = shift; + + if (slxsystem("zypper --non-interactive remove $pkgSelection")) { + die _tr("unable to remove selection (%s)\n", $!); + } + + return 1; +} + +sub updateBasicVendorOS +{ + my $self = shift; + + if (slxsystem("zypper --non-interactive update")) { + if ($! == 2) { + # file not found => zypper isn't installed + die _tr("unable to update this vendor-os, as it seems to lack an installation of zypper!\n"); + } + die _tr("unable to update this vendor-os (%s)\n", $!); + } + + return 1; +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Packager/Base.pm b/src/installer/OpenSLX/OSSetup/Packager/Base.pm new file mode 100644 index 00000000..af600b8b --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Packager/Base.pm @@ -0,0 +1,98 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# Base.pm +# - provides empty base of the OpenSLX OSSetup::Packager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Packager::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use Scalar::Util qw( weaken ); + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + confess "Creating OpenSLX::OSSetup::Packager::Base-objects directly makes no sense!"; +} + +sub initialize +{ + my $self = shift; + my $engine = shift; + + $self->{'engine'} = $engine; + weaken($self->{'engine'}); + # avoid circular reference between packager and its engine + + return; +} + +sub prepareBootstrap +{ +} + +sub bootstrap +{ +} + +sub importTrustedPackageKeys +{ +} + +sub installPackages +{ +} + +sub getInstalledPackages +{ +} + +1; +################################################################################ + +=pod + +=head1 NAME + +OpenSLX::OSSetup::Packager::Base - the base class for all OSSetup::Packagers + +=head1 SYNOPSIS + + package OpenSLX::OSSetup::Packager::coolnewpkg; + + use vars qw(@ISA $VERSION); + @ISA = ('OpenSLX::OSSetup::Packager::Base'); + $VERSION = 1.01; + + use coolnewpkg; + + sub new + { + my $class = shift; + my $self = {}; + return bless $self, $class; + } + + # override all methods of OpenSLX::OSSetup::Packager::Base in order to + # implement the support for a new packager + ... + +I> + +=cut diff --git a/src/installer/OpenSLX/OSSetup/Packager/dpkg.pm b/src/installer/OpenSLX/OSSetup/Packager/dpkg.pm new file mode 100644 index 00000000..94aff9c6 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Packager/dpkg.pm @@ -0,0 +1,102 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# rpm.pm +# - provides rpm-specific overrides of the OpenSLX::OSSetup::Packager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Packager::dpkg; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Packager::Base); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'dpkg', + }; + return bless $self, $class; +} + +sub prepareBootstrap +{ + my $self = shift; + my $stage1aDir = shift; + + copyBinaryWithRequiredLibs({ + 'binary' => '/usr/bin/perl', + 'targetFolder' => "$stage1aDir/usr/bin", + 'libTargetFolder' => $stage1aDir, + }); + +} + +sub bootstrap +{ + my $self = shift; + my $pkgs = shift; + + my $debootstrapPkg = $pkgs->[0]; + chdir '..'; + vlog(2, "unpacking debootstrap ..."); + if (slxsystem("ash", "-c", "ar x slxbootstrap/$debootstrapPkg")) { + die _tr("unable to unarchive package '%s' (%s)", $debootstrapPkg, $!); + } + if (slxsystem("ash", "-c", "tar xzf data.tar.gz")) { + die _tr("unable to untar 'data.tar.gz (%s)", $!); + } + if (slxsystem("ash", "-c", "rm -f debian-binary *.tar.gz")) { + die _tr("unable to cleanup package '%s' (%s)", $debootstrapPkg, $!); + } + my $arch = $self->{engine}->{'distro-info'}->{arch}; + my $releaseName = $self->{engine}->{'distro-info'}->{'release-name'}; + my $baseURL = $self->{engine}->{baseURLs}->[0]; + my $debootstrapCmd = unshiftHereDoc(<<" END-OF-HERE"); + /usr/sbin/debootstrap --arch $arch $releaseName \\ + /slxbootstrap/slxfinal $baseURL + END-OF-HERE + if (slxsystem("ash", "-c", ". $debootstrapCmd")) { + die _tr("unable to run debootstrap (%s)", $!); + } + return; +} + +sub installPackages +{ + my $self = shift; + my $pkgs = shift; + my $finalPath = shift; + + return unless defined $pkgs && @$pkgs; + + if (slxsystem("dpkg", "--root=$finalPath", "--install", @$pkgs)) { + die _tr("error during package-installation (%s)\n", $!); + } + return; +} + +sub getInstalledPackages +{ + my $self = shift; + + my $rpmCmd = 'dpkg-query --showformat "\${package}\n" --show'; + my $pkgList = qx{$rpmCmd}; + return split "\n", $pkgList; +} + +1; diff --git a/src/installer/OpenSLX/OSSetup/Packager/rpm.pm b/src/installer/OpenSLX/OSSetup/Packager/rpm.pm new file mode 100644 index 00000000..8a86a3d2 --- /dev/null +++ b/src/installer/OpenSLX/OSSetup/Packager/rpm.pm @@ -0,0 +1,89 @@ +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +# rpm.pm +# - provides rpm-specific overrides of the OpenSLX::OSSetup::Packager API. +# ----------------------------------------------------------------------------- +package OpenSLX::OSSetup::Packager::rpm; + +use strict; +use warnings; + +use base qw(OpenSLX::OSSetup::Packager::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'name' => 'rpm', + }; + return bless $self, $class; +} + +sub bootstrap +{ + my $self = shift; + my $pkgs = shift; + + foreach my $pkg (@$pkgs) { + vlog(2, "unpacking package $pkg..."); + if (slxsystem("ash", "-c", "rpm2cpio $pkg | cpio -i -d -u")) { + die _tr("unable to unpack package <%s> (%s)", $pkg, $!); + } + } + return; +} + +sub importTrustedPackageKeys +{ + my $self = shift; + my $keyFiles = shift; + my $finalPath = shift; + + return unless defined $keyFiles; + + foreach my $keyFile (@$keyFiles) { + vlog(2, "importing package key $keyFile..."); + if (slxsystem("rpm", "--root=$finalPath", "--import", "$keyFile")) { + die _tr("unable to import package key <%s> (%s)\n", $keyFile, $!); + } + } + return; +} + +sub installPackages +{ + my $self = shift; + my $pkgs = shift; + my $finalPath = shift; + + return unless defined $pkgs && scalar(@$pkgs); + + if (slxsystem("rpm", "--root=$finalPath", "-ivh", @$pkgs)) { + die _tr("error during package-installation (%s)\n", $!); + } + return; +} + +sub getInstalledPackages +{ + my $self = shift; + + my $rpmCmd = 'rpm -qa --queryformat="%{NAME}\n"'; + my $pkgList = `$rpmCmd`; + return split "\n", $pkgList; +} + +1; diff --git a/src/installer/slxos-export b/src/installer/slxos-export new file mode 100755 index 00000000..8c0733ab --- /dev/null +++ b/src/installer/slxos-export @@ -0,0 +1,323 @@ +#! /usr/bin/perl +# ----------------------------------------------------------------------------- +# Copyright (c) 2006, 2007 - 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/ +# ----------------------------------------------------------------------------- +use strict; +use warnings; + +my $abstract = q[ +slxos-export + OpenSLX-script to generate an export from a vendor-OS. +]; + +use Encode; +use Getopt::Long qw(:config pass_through); +use Pod::Usage; + +# add the folder this script lives in and the lib-folder to perl's +# search path for modules: +use FindBin; +use lib "$FindBin::RealBin"; +use lib "$FindBin::RealBin/../lib"; + +use lib "$FindBin::RealBin/../config-db"; +# development path to config-db + +use OpenSLX::Basics; +use OpenSLX::OSExport::Engine; +use OpenSLX::Utils; + +my %option; + +GetOptions( + 'help|?' => \$option{helpReq}, + 'man' => \$option{manReq}, + 'version' => \$option{versionReq}, + ) + or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $option{helpReq}; +if ($option{manReq}) { + # avoid dubious problem with perldoc in combination with UTF-8 that + # leads to strange dashes and single-quotes being used + $ENV{LC_ALL} = 'POSIX'; + pod2usage(-verbose => 2); +} +if ($option{versionReq}) { + system('slxversion'); + exit 1; +} + +openslxInit(); + +my $action = shift @ARGV || ''; + +if ($action =~ m[^list-ex]i) { + print _tr("List of exported vendor-OSes (exports):\n"); + foreach my $type (sort keys %supportedExportFileSystems) { + # list all image files, followed by the block devices using it: + my @files = map { + my $image = decode('utf8', $_); + $image =~ s[^.+/][]; + $image; + } + sort glob("$openslxConfig{'public-path'}/export/$type/*"); + my %imageFiles; + foreach my $file (@files) { + if ($file =~ m[^(.+)@(.+)$]) { + # it's a link referring to a block device using this image, + # we collect the name of the block device: + push @{$imageFiles{$1}}, $2; + } else { + # it's an image file, we setup an empty array of block devices: + $imageFiles{$file} = []; + } + } + print join( + '', + map { + my $devices = join(',', @{$imageFiles{$_}}); + my $name = "${_}::$type"; + if (length($devices)) { + "\t$name".substr(' ' x 30, length($name))."($devices)\n"; + } else { + "\t$name\n"; + } + } + grep { + # filter out RSYNC_TMP folders: + $_ !~ m[###]; + } + sort keys %imageFiles + ); + } +} elsif ($action =~ m[^list-in]i) { + my @vendorOSDirs + = grep { -d $_ } glob("$openslxConfig{'private-path'}/stage1/*"); + print _tr("List of installed vendor-OSes:\n"); + print join( + '', + map { + my $vendorOS = decode('utf8', $_); + $vendorOS =~ s[^.+/][]; + "\t$vendorOS\n"; + } + sort @vendorOSDirs + ); +} elsif ($action =~ m[^list-ty]i) { + print _tr("List of supported export types:\n\t"); + print join("\n\t", sort @supportedExportTypes) . "\n"; +} elsif ($action =~ m[^export]i) { + if (scalar(@ARGV) != 2) { + print STDERR _tr( + "You need to specify exactly one vendor-os-name and one export-type!\n" + ); + pod2usage(2); + } + my $vendorOSName = shift @ARGV; + my $exportType = shift @ARGV; + + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + + # create OSExport-engine for given export type and start it: + my $engine = OpenSLX::OSExport::Engine->new; + $engine->initializeForNew($vendorOSName, $exportType); + if (!-e $engine->{'vendor-os-path'}) { + die _tr("vendor-OS '%s' doesn't exist, giving up!\n", + $engine->{'vendor-os-path'}); + } + $engine->exportVendorOS(); +} elsif ($action =~ m[^remove]i) { + if (scalar(@ARGV) != 1) { + print STDERR _tr("You need to specify exactly one export-name!\n"); + pod2usage(2); + } + my $exportName = shift @ARGV; + + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + + # create OSExport-engine for given export type and start it: + my $engine = OpenSLX::OSExport::Engine->new; + $engine->initializeFromExisting($exportName); + $engine->purgeExport(); +} else { + vlog(0, _tr(unshiftHereDoc(<<' END-OF-HERE'), $0)); + You need to specify exactly one action: + export + list-exported + list-installed + list-types + remove + Try '%s --help' for more info. + END-OF-HERE +} + +=head1 NAME + +slxos-export - OpenSLX-script to generate an export from a vendor-OS. + +=head1 SYNOPSIS + +slxos-export [options] + +=head3 Options + + --help brief help message + --log-level= level of logging verbosity (0-3) + --man show full documentation + --version show version + +=head3 Actions + +=over 8 + +=item B<< export >> + +exports the vendor-OS with the given name using the given export type and +adds it to the config-DB, too. The export will be named as the vendor-OS, +but with an additional '-' appended to it (where will be replaced +by the chosen export-type). + +=item B<< list-exported >> + +list all exported vendor-OSes + +=item B<< list-installed >> + +list all installed vendor-OSes + +=item B<< list-types >> + +list all supported export types + +=item B<< remove >> + +removes the export with the given name from disk and config-DB + +=back + +=head1 DESCRIPTION + +B converts an installed vendor-OS into a form that can be accessed +via network by booting clients. + +The resulting form of such a conversion is called an I and those come +in different flavors: + +=over 8 + +=item B< Export Type 'nfs'> + +NFS (network file system) is a well established networking file system, which +is supported by LINUX since long. + +=item B< Export Type 'sqfs-nbd'> + +Squash-FS is a rather modern filesystem providing very good compression, +resulting in considerably reduced network traffic during boot (and execution). +However, in order to mount a squash-fs that resides on the server, the client +has to get access to it first. This can be established via a network block +device, which basically "transports" a block device over the network (from +server to client), making it possible to use more or less any file system over +the network. +So, this example translates to 'use a squashfs on a network block device'. + +=back + +When invoking slxos-export, you have to pass it a vendor-OS name and the export +type you want to use and it will do the conversion (which can take a while, so +please be patient). + +The resulting export will be stored under C. + +=head1 OPTIONS + +=over 4 + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--version> + +Prints the version and exits. + +=back + +=head1 EXAMPLES + +=over 8 + +=head3 Exporting a Vendor-OS via NFS + +=item B<< slxos-export export suse-10.2 nfs >> + +Exports the installed vendor-OS suse-10.2 via nfs, the +resulting NFS-export will live in C. + +=back + +=head3 Exporting a Vendor-OS via NBD + +=over 8 + +=item B<< slxos-export export ubuntu-6.10 sqfs-nbd >> + +Exports the installed vendor-OS ubuntu-6.10 via nbd, the resulting +Squash-FS will live in C. + +=back + +=head3 Removing an Export + +=over 8 + +=item B<< slxos-export remove ubuntu-6.10 nbd >> + +Wipes the squash-FS of the export named 'ubuntu-6.10' from disk (i.e. the +file C will be deleted) and +removes that export from the config-DB, too. + +=back + +=head1 SEE ALSO + +slxsettings, slxos-setup, slxconfig, slxconfig-demuxer + +=head1 GENERAL OPENSLX OPTIONS + +Being a part of OpenSLX, this script supports several other options +which can be used to overrule the OpenSLX settings: + + --db-name= name of database + --db-spec= full DBI-specification of database + --db-type= type of database to connect to + --locale= locale to use for translations + --log-level= level of logging verbosity (0-3) + --logfile= file to write logging output to + --private-path= path to private data + --public-path= path to public (client-accesible) data + --temp-path= path to temporary data + +Please refer to the C-manpage for a more detailed description +of these options. + +=cut + diff --git a/src/installer/slxos-setup b/src/installer/slxos-setup new file mode 100755 index 00000000..8812a19b --- /dev/null +++ b/src/installer/slxos-setup @@ -0,0 +1,402 @@ +#! /usr/bin/perl +# ----------------------------------------------------------------------------- +# Copyright (c) 2006..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/ +# ----------------------------------------------------------------------------- +use strict; +use warnings; + +my $abstract = q[ +slxos-setup + This script installs an operating system into a folder that can be used as + a stage1 system for OpenSLX. +]; + +use Encode; +use Getopt::Long qw(:config pass_through); +use Pod::Usage; + +# add the folder this script lives in and the lib-folder to perl's +# search path for modules: +use FindBin; +use lib "$FindBin::RealBin"; +use lib "$FindBin::RealBin/../lib"; + +use lib "$FindBin::RealBin/../config-db"; + # development path to config-db + +use OpenSLX::Basics; +use OpenSLX::OSSetup::Engine; +use OpenSLX::Utils; + +my %option; + +GetOptions( + 'help|?' => \$option{helpReq}, + 'man' => \$option{manReq}, + 'version' => \$option{versionReq}, +) or pod2usage(2); +pod2usage(-msg => $abstract, -verbose => 0, -exitval => 1) if $option{helpReq}; +if ($option{manReq}) { + # avoid dubious problem with perldoc in combination with UTF-8 that + # leads to strange dashes and single-quotes being used + $ENV{LC_ALL} = 'POSIX'; + pod2usage(-verbose => 2) +} +if ($option{versionReq}) { + system('slxversion'); + exit 1; +} + +if ($> != 0) { + die _tr("Sorry, this script can only be executed by the superuser!\n"); +} + +openslxInit(); + +my $action = shift @ARGV || ''; + +# create ossetup-engine for given distro and start it: +my $engine = OpenSLX::OSSetup::Engine->new; +if ($action =~ m[^import]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to give the name of the vendor-os you'd like to import!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'import'); + if (!-e $engine->{'vendor-os-path'}) { + die _tr("'%s' doesn't exist, giving up!\n", $engine->{'vendor-os-path'}); + } + $engine->addInstalledVendorOSToConfigDB(); +} elsif ($action =~ m[^update]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to give the name of the vendor-os you'd like to update!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'update'); + $engine->updateVendorOS(); +} elsif ($action =~ m[^shell]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to give the name of the vendor-os you'd like to start of shell for!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'shell'); + $engine->startChrootedShellForVendorOS(); +} elsif ($action =~ m[^install]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to give the name of the vendor-os you'd like to install!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'install'); + $engine->installVendorOS(); +} elsif ($action =~ m[^clone]i) { + my $source = shift @ARGV; + my $vendorOSName = shift @ARGV; + if (!defined $source || !defined $vendorOSName) { + print STDERR _tr("You need to specify exactly one source and one vendor-OS-name!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'clone'); + $engine->cloneVendorOS($source); +} elsif ($action =~ m[^remove]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to specify exactly one vendor-OS-name!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'remove'); + $engine->removeVendorOS(); +} elsif ($action =~ m[^list-se]i) { + my $vendorOSName = shift @ARGV; + if (!defined $vendorOSName) { + print STDERR _tr("You need to specify exactly one vendor-OS-name!\n"); + pod2usage(2); + } + # we chdir into the script's folder such that all relative paths have + # a known starting point: + chdir($FindBin::RealBin) + or die _tr("can't chdir to script-path <%> (%s)", $FindBin::RealBin, $!); + $engine->initialize($vendorOSName, 'install'); + print _tr("List of supported selections for '%s':\n", $vendorOSName); + print join('', map { "\t$_\n" } + sort keys %{$engine->{'distro-info'}->{selection}}); +} elsif ($action =~ m[^list-su]i) { + print _tr("List of supported distros:\n"); + print join('', map { + "\t$_" + .(' 'x(20-length($_))) + ."\t($supportedDistros{$_})\n" + } + sort keys %supportedDistros); +} elsif ($action =~ m[^list-in]i) { + print _tr("List of installed vendor-OSes:\n"); + print join( + '', + map { + my $vendorOS = decode('utf8', $_); + $vendorOS =~ s[^.+/][]; + "\t$vendorOS\n"; + } + grep { -d $_ } + sort glob("$openslxConfig{'private-path'}/stage1/*") + ); +} else { + vlog(0, _tr(unshiftHereDoc(<<' END-OF-HERE'), $0)); + You need to specify exactly one action: + clone + import-into-db + install + list-installed + list-selections + list-supported + remove + shell + update + Try '%s --help' for more info. + END-OF-HERE +} + + + +=head1 NAME + +slxos-setup - OpenSLX-script to install a vendor-OS. + +=head1 SYNOPSIS + +slxos-setup [options] ... + +=head3 Options + + --help brief help message + --log-level= level of logging verbosity (0-3) + --man show full documentation + --version show version + +=head3 Actions + +=over 8 + +=item B<< clone >> + +clones an existing operating system via rsync + +=item B<< import-into-db >> + +imports a vendor-OS into the openslx-db + +=item B<< install >> + +installs a vendor-OS into a folder + +=item B<< list-installed >> + +show installed vendor-OSes + +=item B<< list-selections >> + +show available selections for given vendor-OS + +=item B<< list-supported >> + +show supported distros + +=item B<< remove >> + +removes an installed vendor-OS + +=item B<< shell >> + +starts a chrooted shell for an installed vendor-OS + +=item B<< update >> + +updates an installed vendor-OS + +=back + +=head1 DESCRIPTION + +B installs an operating system into a folder which +will be used as a OpenSLX-stage1-system (a.k.a. a I). + +You can either install a vendor-OS from scratch (causing the required +packages to be downloaded or copied from a local source). Installing +is supported for several different LINUX distributions, but not for all +of them. + +Alternatively, a locally installed operating system can be cloned +into a vendor-OS. + +When invoking slxos-setup, you have to pass it the name of the vendor-OS +you wish to create. + +=head1 OPTIONS + +=over 8 + +=item B<--help> + +Prints a brief help message and exits. + +=item B<--man> + +Prints the manual page and exits. + +=item B<--version> + +Prints the version and exits. + +=item B + +The vendor-os-name is the name of the vendor-OS that shall be installed, +cloned, imported or updated. It corresponds to a folder in the OpenSLX- +stage1-path (usually /var/opt/openslx/stage1). +The general format of a vendor-os-name is: + + - +or + -- + +The distro-name is something like 'suse' or 'fedora', and the release-version +is a numerical version, e.g. '10.1' or '6'. + +If you specify a selection, too, you state that you want all the packages +that are provided by the specific selection (many distributions offer several +different package selections for installation, like 'kde' or 'gnome'). +If you do not specify any selection, you will get the default selection of +that distribution. + +If you pass an unknown selection, you will see a list of the selections +that are available. The available selections for any vendor-OS can be requested +via the 'list-selections' action. + +In clone-mode, it is a good idea to specify some unique string as the selection +part of the vendor-os-name, such that you will easily recognize the vendor-OS +at a later stage. We recommend something like '-cloned-from-'. + +=item B + +When cloning a vendor-OS, slxos-setup needs to know where to fetch +the existing OS-files from. Please check the 'rsync' docs for what +format an rsync-uri has. + +=back + +=head1 EXAMPLES + +=head3 Installing a Vendor-OS + +=over 8 + +=item B<< slxos-setup install suse-11.1 >> + +Installs the distro suse-11.1 as a new vendor-OS. + +=item B<< slxos-setup install suse-11.1-gnome >> + +Installs the 'gnome'-selection of distro suse-11.1 as a new +vendor-OS. + +=back + +=head3 Cloning an Operating System to Make a New Vendor-OS + +=over 8 + +=item B<< slxos-setup clone my_server:/ suse-11.1-clone-my_server >> + +Clones the suse-11.1 system from server 'my_server' as a new +vendor-OS, which will be named 'suse-11.1-clone-my_server'. + +=back + +=head3 Updating a Vendor-OS + +=over 8 + +=item B<< slxos-setup update suse-11.1 >> + +Updates the (existing) vendor-OS 'suse-11.1'. + +=back + +=head3 Importing an Existing Vendor-OS into the Config-DB + +=over 8 + +=item B<< slxos-setup import-into-db suse-11.1 >> + +Imports the (existing) vendor-OS 'suse-11.1' into the config-DB. + +=back + +=head3 Removing a Vendor-OS + +=over 8 + +=item B<< slxos-setup remove suse-11.1 >> + +Wipes the (existing) vendor-OS 'suse-11.1' from disk and removes it +from the config-DB, too. + +=back + +=head1 SEE ALSO + +slxsettings, slxos-export, slxconfig, slxconfig-demuxer + +=head1 GENERAL OPENSLX OPTIONS + +Being a part of OpenSLX, this script supports several other options +which can be used to overrule the OpenSLX settings: + + --db-name= name of database + --db-spec= full DBI-specification of database + --db-type= type of database to connect to + --locale= locale to use for translations + --log-level= level of logging verbosity (0-3) + --logfile= file to write logging output to + --private-path= path to private data + --public-path= path to public (client-accesible) data + --temp-path= path to temporary data + +Please refer to the C-manpage for a more detailed description +of these options. + +=cut -- cgit v1.2.3-55-g7522