# 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 = ""; my $exportBD = ""; $exportFS = lc($1) if defined $1; $exportBD = lc($2) if defined $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