goto-fai/ 0000755 0001750 0001750 00000000000 11415400612 012077 5 ustar benoit benoit goto-fai/ldap2fai 0000755 0001750 0001750 00000037652 11415400612 013524 0 ustar benoit benoit #!/usr/bin/perl -w
#
# Copyright (c) 2008 Landeshauptstadt München
# Copyright (c) 2008-2010 GONICUS GmbH
#
# Authors: Jan-Marek Glogowski
# Cajus Pollmeier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
#
=head1 NAME
ldap2fai - read FAI config from LDAP and create config space.
=head1 SYNOPSIS
ldap2fai [-hnvW] [-c config] [-D bind_dn ] [-w bind password] [-d dump_dir] [-H hostname]
=head1 OPTIONS
B<-h>, B<--help>
print out this help message
B<-v>, B<--verbose>
be verbose (multiple v's will increase verbosity)
B<-n>, B<--foreground>
dry run (includes verbose)
B<-c>
LDAP config file (default: /etc/ldap/ldap.conf)
B<-d>
output dir (default: /var/lib/fai/config)
B<-D>
bind dn
B<-W>
prompt for password
B<-w>
read password from command line
B<-H>
check hostname
=head1 DESCRIPTION
ldap2fai is a script to create read the fai config from LDAP and create fai config space.
=head1 BUGS
Please report any bugs, or post any suggestions, to the GOsa mailing list or to
=head1 LICENCE AND COPYRIGHT
This code is part of GOsa (L)
COPYRIGHT
Copyright (c) 2008 Landeshauptstadt München
Copyright (c) 2008-2010 GONICUS GmbH
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
=cut
use strict;
use warnings;
use Net::LDAP;
use Net::LDAP::Util qw(:escape);
use Getopt::Long;
use File::Path;
use GOsa::Common qw(:ldap :misc);
use GOsa::FAI qw(:flags);
my $bind_dn;
my $bind_pwd;
my $prompt_pwd;
my $ldapuris;
my $ldap_conf = "/etc/ldap/ldap.conf";
my $dump_dir = "/var/lib/fai/config";
my $verbose = 0;
my $print_classes = 0;
my( $hostname, $host_base, $host_dn, $host_tag );
my $fai_mirror;
my $dry_run = 0;
my $release_var = 'FAIclientRelease';
my $check_hostname;
my $kernel;
Getopt::Long::Configure ("bundling");
GetOptions( 'v|verbose' => \$verbose,
'h|help' => \&usage,
'c|config=s' => \$ldap_conf,
'd|dump-dir=s' => \$dump_dir,
'D|bind-dn=s' => \$bind_dn,
'n|dry-run' => \$dry_run,
'W|prompt-pwd' => \$prompt_pwd,
'w|password=s' => \$bind_pwd,
'H|hostname=s' => \$check_hostname )
or usage( 'Wrong parameters' );
# If we use dry-run, be verbose
$verbose = 1 if( $dry_run );
# Get MAC from cmdline
my $mac = shift @ARGV;
$mac eq '' && usage( "MAC address not specified." );
usage( "No valid MAC address specified." )
if( ! ($mac =~ m/^([0-9a-f]{2}:){5}[0-9a-f]{2}/i) );
# Is dump_dir a directory
if( ! $dry_run ) {
-d "$dump_dir"
|| usage("'$dump_dir' is not a directory.\n");
}
# initialize ldap
my $init_results =
gosa_ldap_init( $ldap_conf, 0, $bind_dn, $prompt_pwd, $bind_pwd );
do_exit( 3, $init_results ) if( 'HASH' ne ref( $init_results ) );
my $ldap = $init_results->{ 'HANDLE' };
my $base = $init_results->{ 'BASE' };
# Get FAI object
my $faiobj = GOsa::FAI->new( 'LDAP' => $ldap,
'base' => $base,
'dumpdir' => $dump_dir );
# Set FAI flags
$faiobj->flags( FAI_FLAG_VERBOSE ) if( $verbose );
$faiobj->flags( FAI_FLAG_VERBOSE | FAI_FLAG_DRY_RUN ) if( $dry_run );
my $class_str = get_classes( $mac );
print( " + FAIclass string: $class_str\n" ) if( $verbose );
my ($res_classlist, $release) = $faiobj->resolve_classlist( $class_str );
if( 'ARRAY' eq ref( $res_classlist ) ) {
if( $verbose ) {
print( " + Release: $release\n" );
print( " + Resolved classlist: " . join( ' ', @$res_classlist ) . "\n" );
}
}
else { do_exit( 8, $res_classlist ); }
if( ! $dry_run ) {
create_dir( "$dump_dir/class" );
open (FAICLASS,">$dump_dir/class/${hostname}")
|| do_exit( 4, "Can't create $dump_dir/class/${hostname}. $!\n" );
print( FAICLASS join( ' ', @$res_classlist ) );
close( FAICLASS );
}
$res_classlist = $faiobj->expand_fai_classlist( $res_classlist, $hostname );
if( 'ARRAY' eq ref( $res_classlist ) ) {
print( " + FAI classlist: " . join( ' ', @$res_classlist ) . "\n" )
if( $verbose );
}
print( "Extending FAI classtree with real objects...\n" );
$faiobj->extend_class_cache( $release );
print( "Dumping config space to '$dump_dir'...\n" );
my( $sections, $error ) = $faiobj->dump_release( $release, $res_classlist, $hostname );
print $error . "\n" if( defined $error );
if( defined ${hostname} ) {
if( open( HOSTVARS, ">> ${dump_dir}/class/${hostname}.var" ) ) {
print( HOSTVARS "FAIclientRelease='$release'\n" );
print( HOSTVARS "MAXPACKAGES=20000\n" );
print( HOSTVARS "printk=0\n" );
print( HOSTVARS "STOP_ON_ERROR=700\n" );
close( HOSTVARS );
}
}
generate_sources_list( $sections );
generate_kernel_packagelist( $kernel );
$ldap->unbind(); # take down session
$ldap->disconnect();
exit 0;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sub usage
{
(@_) && print STDERR "\n@_\n\n";
print STDERR << "EOF";
usage: $0 [-hnvW] [-c config] [-D bind_dn ] [-w bind password] [-d dump_dir] [-H hostname]
-h : this (help) message
-n : dry run (includes verbose)
-v : be verbose
-c : LDAP config file (default: ${ldap_conf})
-d : dump dir (default: ${dump_dir})
-D : bind dn
-W : prompt for password
-w : read password from command line
-H : check hostname
EOF
exit -1;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
sub do_exit {
my ($code,$msg) = @_;
my @exit_msg = (
0, # Ok
0, # Usage
0, # LDAP error
0, # No entries found
0, # Create file
0, # Mkdir (5)
0, # LDAP lookup
0, # FAI object
"No releases found in classlist. Releases are classes starting with ':'.",
"Multiple releases found! Fix your classes or profiles.\n",
0, # Hostname mismatch (10)
0, # Release object not found
0, # Multiple profiles
);
if( ! defined $msg ) {
if( exists $exit_msg[ $code ] ) {
$msg = $exit_msg[ $code ];
}
}
else {
if( ! exists $exit_msg[ $code ] ) {
$msg .= "\nMissing exit ID - assign one!";
}
elsif( $exit_msg[ $code ] ) {
$msg .= "\n" . $exit_msg[ $code ];
}
}
print( "$msg\n" ) if( defined $msg );
$ldap->unbind() if( defined $ldap );
exit( -1 * $code );
}
sub create_dir
{
if( ! -d "$_[0]" ) {
return if( $dry_run );
eval {
mkpath "$_[0]";
};
do_exit( 5, "Can't create dir $_[0]: $!\n" ) if( $@ );
}
}
sub get_classes {
# return list of FAI classes defined for host
my $mac = shift;
my (@classes,$mesg,$entry);
my $host_info;
my $real_hostname;
print( "Lookup host for MAC '$mac'...\n" ) if( $verbose );
my $filter = "(&(objectClass=goHard)(macAddress=$mac))";
$mesg = $ldap->search(
base => "$base",
filter => $filter,
attrs => [ 'FAIclass', 'cn', 'FAIdebianMirror', 'gosaUnitTag', 'gotoBootKernel' ]);
$mesg->code && do_exit( 2, sprintf( "LDAP error: %s (%i)", $mesg->error, __LINE__ ) );
# normally, only one value should be returned
if( 1 != $mesg->count ) {
if( 0 == $mesg->count ) {
do_exit( 3, "LDAP search for client failed!\n"
. "No entries have been returned.\n"
. " - Base: $base\n"
. " - Filter: $filter\n" );
}
else {
do_exit( 3, "LDAP search for client failed!\n"
. $mesg->count . " entries have been returned.\n"
. " - Base: $base\n"
. " - Filter: $filter\n" );
}
}
# get the entry, host DN and hostname
$entry = ($mesg->entries)[0];
$host_dn = $entry->dn;
$hostname = $entry->get_value( 'cn' );
$host_tag = $entry->get_value( 'gosaUnitTag' );
$kernel = $entry->get_value( 'gotoBootKernel' );
$real_hostname = $hostname;
$faiobj->tag( $host_tag ) if( defined $host_tag );
# set $host_base
my @rdn = gosa_ldap_split_dn( $host_dn );
shift( @rdn ); # hostname
shift( @rdn ); # servers / workstations / terminals
shift( @rdn ); # systems
$host_base = join( ',', @rdn );
# strip domain from LDAP hostname for FAI class
$hostname =~ s/\..*//;
$host_info = " + Host DN: $host_dn\n"
. " + Base: $host_base\n"
. " + Hostname: $hostname";
$host_info .= ' (' . $real_hostname . ')'
if ( $hostname ne $real_hostname );
$host_info .= "\n";
# Check for hostname mismatch
if( defined $check_hostname ) {
if( $real_hostname !~ m/^${check_hostname}$/i ) {
# Try stripped domain (non-FQDN) hostname
do_exit( 10, "Hostname mismatch: net='$check_hostname', "
. "LDAP='$real_hostname', non-FQDN='$hostname'" )
if( $hostname !~ m/^${check_hostname}$/i );
}
}
# check, if we have a FAIclass value, otherwise check groups
my $fai_class_str = $entry->get_value( 'FAIclass' );
if( (! defined $fai_class_str) || ('' eq $fai_class_str) ) {
print( "No FAI information stored in host object - looking for host groups...\n" ) if( $verbose );
$filter = '(&(member=' . escape_filter_value(${host_dn}) . ')(objectClass=gosaGroupOfNames)(gosaGroupObjects=[W])(objectClass=FAIobject))';
$mesg = $ldap->search(
base => "$base",
filter => $faiobj->prepare_filter( $filter ),
attrs => [ 'FAIclass', 'cn', 'FAIdebianMirror', 'gotoBootKernel' ]);
$mesg->code && do_exit( 2, sprintf( "LDAP error: %s (%i)", $mesg->error, __LINE__ ) );
if( 1 != $mesg->count ) {
if( 0 == $mesg->count ) {
do_exit( 3, "LDAP search for object groups with FAIobject containing the client failed!\n"
. "No entries have been returned.\n"
. " - Base: $base\n"
. " - Filter: $filter\n" );
}
else {
do_exit( 3, "LDAP search for object groups with FAIobject containing the client failed!\n"
. $mesg->count . " entries have been returned.\n"
. " - Base: $base\n"
. " - Filter: $filter\n" );
}
}
$entry = ($mesg->entries())[0];
print( "Found FAI information in object group '" . $entry->get_value( 'cn' ) . "'\n"
. ' + Object group: ' . $entry->dn() . "\n" )
if( $verbose );
if (not defined $kernel){
$kernel = $entry->get_value( 'gotoBootKernel' );
}
}
if (not defined $kernel){
do_exit( 3, "There is no kernel defined for this client: check the gotoBootKernel attribute!\n" );
}
$fai_mirror = $entry->get_value( 'FAIdebianMirror' );
print( $host_info ) if $verbose;
return $entry->get_value( 'FAIclass' );
}
sub generate_sources_list {
my( $sections ) = @_;
my( $mesg, $entry, $line, @deblines, @modsections, @rdns, %saw, $debline );
# Create unique list
undef %saw;
@saw{@$sections} = ();
@$sections = sort keys %saw;
if ($verbose) {
print "Generate template '/etc/apt/sources.list' for class 'LAST'\n"
. " - searching server(s) for\n"
. " + release: ${release}\n"
. " + sections: @$sections\n";
}
create_dir( "${dump_dir}/files/etc/apt/sources.list" );
if( ! $dry_run ) {
open (SOURCES,">${dump_dir}/files/etc/apt/sources.list/LAST")
|| do_exit( 4, "Can't create ${dump_dir}/files/etc/apt/sources.list/LAST. $!\n" );
}
if( "auto" ne "$fai_mirror" ) {
if( ! $dry_run ) {
print SOURCES "deb $fai_mirror $release @$sections\n";
close (SOURCES);
}
print( " = Using default: $fai_mirror\n" ) if( $verbose );
return 0;
}
my %release_sections = ();
my @sec = @$sections;
my ($search_base,@entries);
$release_sections{ "$release" } = \@sec;
my $fin = 0;
while( 1 ) {
# Prepare search base
if( ! defined $search_base )
{ $search_base = $host_base; }
else {
my @rdn = gosa_ldap_split_dn( $search_base );
shift( @rdn );
$search_base = join( ',', @rdn );
}
print( " - using search start base: $search_base\n" ) if $verbose;
# Look for repository servers
($mesg,$search_base) = gosa_ldap_rsearch( $ldap, $host_base, '',
$faiobj->prepare_filter( '(objectClass=FAIrepositoryServer)' ),
'one', 'ou=servers,ou=systems', [ 'FAIrepository', 'cn' ] );
goto BAILOUT_CHECK_SERVER if( ! defined $mesg );
$mesg->code && do_exit
( 2, sprintf( "LDAP error: %s (%i)", $mesg->error, __LINE__ ) );
if( 0 == scalar $mesg->entries ) {
next;
}
# Check all found servers
print( " - found matches in base: $search_base\n" )
if( $verbose && $mesg->count() );
$fin = 1;
foreach $entry ($mesg->entries) {
print " - inspecting repository server: "
. $entry->get_value('cn') . "\n" if $verbose;
foreach my $repoline ($entry->get_value('FAIrepository')){
my (@items) = split( '\|', ${repoline} );
my (@modsections) = split( ',', $items[3] );
# Check repository release
if( exists $release_sections{ $items[ 2 ] } ) {
# Check sections
# Idea: try to remove local section from global section list.
# If not remove, removed from local list
# and add to
my $index = 0;
foreach my $section (@modsections) {
if( 0 == gosa_array_find_and_remove
( $release_sections{ $items[ 2 ] }, $section ) )
{
splice( @modsections, $index, 1 );
if( 0 == scalar $release_sections{ $items[ 2 ] } ) {
delete $release_sections{ $items[ 2 ] };
last;
}
}
$index++;
}
# Add deb-line for server, if we have local sections
if( scalar @modsections > 0 ) {
$debline = "deb $items[ 0 ] $items[ 2 ] " . join(' ',@modsections) . "\n";
print " + add: $debline" if $verbose;
print SOURCES "$debline" if( ! $dry_run );
}
last if( 0 == scalar keys ( %release_sections ) );
}
}
# Check, if there we still have some sections in any release
while ( my ($key, $value) = each(%release_sections) ) {
if (0 != scalar @$value) {
$fin = 0;
last;
}
}
last if (1 == $fin);
}
last if(1 == $fin);
}
BAILOUT_CHECK_SERVER:
if( 0 == $fin ) {
if( $verbose ) {
print "Missing sections for release:\n";
while ( my ($key, $value) = each(%release_sections) ) {
print " + $key: @$value\n"
}
}
exit -2;
}
close (SOURCES) if( ! $dry_run );
}
sub generate_kernel_packagelist {
my $kernel= shift;
my( $mesg, $entry, $line, @deblines, @modsections, @rdns, %saw, $debline );
# Some fallback for "default" values
if( $kernel eq "default" ) {
$kernel= "linux-image-2.6-486";
}
if ($verbose) {
print "Generate kernel package script for class 'LAST'\n"
. " - kernel: ${kernel}\n"
}
create_dir( "${dump_dir}/scripts/LAST" );
if( ! $dry_run ) {
open (SOURCES,">${dump_dir}/scripts/LAST/99-install-kernel")
|| do_exit( 4, "Can't create ${dump_dir}/scripts/LAST/99-install-kernel. $!\n" );
print SOURCES "#!/bin/sh\n";
print SOURCES "# - automatically created by ldap2fai -\n";
print SOURCES "\$ROOTCMD aptitude -o \"Aptitude::CmdLine::Ignore-Trust-Violations=yes\" -y install $kernel\n";
close (SOURCES);
chmod 0700, "${dump_dir}/scripts/LAST/99-install-kernel";
}
}
# vim:ts=2:sw=2:expandtab:shiftwidth=2:syntax:paste
goto-fai/ldap2fai-loc 0000755 0001750 0001750 00000000217 11346132434 014271 0 ustar benoit benoit #!/bin/sh
if [ -d "$FAI" ]; then
ldap2fai -v -d $FAI $(ifconfig | grep "eth0" | awk '{ print $5; }')
else
echo "No \$FAI found - aborted"
fi
goto-fai/fai-softupdate 0000755 0001750 0001750 00000000530 11346132434 014745 0 ustar benoit benoit #!/bin/sh
fai_running
{
ps ax | grep "fai.*softupdate" | grep -v fai-softupdate | grep -vq "grep"
return $?
}
# Wait until FAI is ready
while fai_running; do sleep 2; done
# Call softupdate and notify users
[ -e /usr/bin/goto-notify ] && goto-notify start-update
fai -N softupdate
[ -e /usr/bin/goto-notify ] && goto-notify stop-update
goto-fai/ldap2fai.1 0000644 0001750 0001750 00000012471 11415400612 013650 0 ustar benoit benoit .\" Automatically generated by Pod::Man 2.1801 (Pod::Simple 3.07)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.ie \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.el \{\
. de IX
..
.\}
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "LDAP2FAI 1"
.TH LDAP2FAI 1 "2010-05-19" "perl v5.10.0" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
ldap2fai \- read FAI config from LDAP and create config space.
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
ldap2fai [\-hnvW] [\-c config] [\-D bind_dn ] [\-w bind password] [\-d dump_dir] [\-H hostname] <\s-1MAC\s0>
.SH "OPTIONS"
.IX Header "OPTIONS"
\&\fB\-h\fR, \fB\-\-help\fR
print out this help message
.PP
\&\fB\-v\fR, \fB\-\-verbose\fR
be verbose (multiple v's will increase verbosity)
.PP
\&\fB\-n\fR, \fB\-\-foreground\fR
dry run (includes verbose)
.PP
\&\fB\-c\fR
\s-1LDAP\s0 config file (default: /etc/ldap/ldap.conf)
.PP
\&\fB\-d\fR
output dir (default: /var/lib/fai/config)
.PP
\&\fB\-D\fR
bind dn
.PP
\&\fB\-W\fR
prompt for password
.PP
\&\fB\-w\fR
read password from command line
.PP
\&\fB\-H\fR
check hostname
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
ldap2fai is a script to create read the fai config from \s-1LDAP\s0 and create fai config space.
.SH "BUGS"
.IX Header "BUGS"
Please report any bugs, or post any suggestions, to the GOsa mailing list or to
.SH "LICENCE AND COPYRIGHT"
.IX Header "LICENCE AND COPYRIGHT"
This code is part of GOsa ()
.PP
\&\s-1COPYRIGHT\s0
Copyright (c) 2008 Landeshauptstadt MA\*~Xnchen
Copyright (c) 2008\-2010 \s-1GONICUS\s0 GmbH
.PP
This program is distributed in the hope that it will be useful,
but \s-1WITHOUT\s0 \s-1ANY\s0 \s-1WARRANTY\s0; without even the implied warranty of
\&\s-1MERCHANTABILITY\s0 or \s-1FITNESS\s0 \s-1FOR\s0 A \s-1PARTICULAR\s0 \s-1PURPOSE\s0. See the
\&\s-1GNU\s0 General Public License for more details.
goto-fai/get-config-dir-gosa 0000755 0001750 0001750 00000004513 11415400612 015555 0 ustar benoit benoit #!/bin/bash
# (c) 2007-2008 Jan-Marek Glogowski
# (c) 2008 Cajus Pollmeier
# (c) 2009-2010 Benoit Mortier
trap '' INT
### BEGIN SUBROUTINE INFO
# Provides-Var:
# Requires-Var: $FAI $action
# Suggests-Var:
# Short-Description: get $FAI from an ldap server.
### END SUBROUTINE INFO
# Start si client
pkill gosa-si-client &> /dev/null
/usr/sbin/gosa-si-client -vvvvvvvvvv
# Wait for the si-client to get up
while [ ! -f /var/run/gosa-si/gosa-si-client.opts ]; do sleep 0.5; done
. /var/run/gosa-si/gosa-si-client.opts
. /usr/lib/goto/goto-support.lib
if [ "$action" != "softupdate" ]; then
echo "* setting hostname: $HOSTNAME"
hostname "$HOSTNAME"
fi
# If we're very slow, wait for the ldap.conf
if [ "$LDAP_AVAILABLE" ]; then
echo "* waiting for LDAP configuration"
while [ ! -f /etc/ldap/ldap.conf ]; do echo "."; sleep 1; done
fi
# Check if autosetup is needed at this point
echo "* GOto configurator started"
if ! terminal_activated $MAC; then
# Cancel softupdate on non-activated systems
if [ "softupdate" != "$action" ]; then
# wait till we get activated - need to be pushed twice here...
echo "goto-activation-start" >> $LOGDIR/fai.log
echo "* GOto waiting for activation..."
while [ ! -f /var/run/gosa-si/gosa-si-client.activated ]; do sleep 1; done
# GOsa writes the GOto entry in three steps. To continue, we check
# if XDRIVER is present.
while ! terminal_load_hardware_profile $MAC &> /dev/null; do
cat "/etc/sysconfig/GOto" | grep -v 'XDRIVER="unknown"' | grep -q 'XDRIVER' && break
sleep 5
done
# Activated!
echo "goto-activation-stop" >> $LOGDIR/fai.log
echo "* GOto system activated"
if terminal_reboot_needed $MAC; then
faireboot
while true; do sleep 1; done
fi
fi
fi
# Wait for LDAP config which may not be available yet
echo "* waiting for LDAP configuration"
while [ ! -f /etc/ldap/ldap.conf ]; do sleep 1; done
# Create configuration space
ldap2fai -v -d ${FAI} -H $HOSTNAME $MAC | tee $LOGDIR/ldap2fai.log
if [ 0 -ne $? ]; then
task error 500 1 "$(< $LOGDIR/ldap2fai.log)\n\nPress enter to reboot." 15 60
fi
# Provide /etc/sysconfig/GOto
terminal_load_hardware_profile $MAC
# vim:ts=2:sw=2:expandtab:shiftwidth=2:syntax:paste
goto-fai/extrbase.DEFAULT 0000755 0001750 0001750 00000002162 11415400612 014726 0 ustar benoit benoit #!/bin/sh
sendmon "TASKBEGIN extrbase"
fs=$FAI_ROOT/etc/fstab
# What's our mirror?
mirror="$(sed '1s/^[^ ]* \([^ ]*\).*$/\1/' $FAI/files/etc/apt/sources.list/LAST)"
options="$(sed -n 's/^FAI_DEBOOTSTRAP_OPTS=.\(.*\).$/\1/p' /etc/fai/make-fai-nfsroot.conf)"
scriptsdir=$([ -d /usr/lib/debootstrap/scripts/ ] && echo '/usr/lib/debootstrap/scripts/' || echo '/usr/share/debootstrap/scripts/')
if [ "x" = "x${FAIdistributionBase}" ]; then
FAIdistributionBase="$FAIclientRelease"
fi
echo "Bootstrapping Debian base system"
echo "+ mirror : $mirror"
echo "+ release: $FAIclientRelease"
echo "+ base: $FAIdistributionBase"
echo "- exec (debootstrap $options $FAIclientRelease $FAI_ROOT $mirror ${scriptsdir}${FAIdistributionBase})"
# Run debootstrap - needs to run in a subshell, since env seems to
# be broken?! debootstrap otherwise cancels after extracting
debootstrap --verbose $options $FAIclientRelease $FAI_ROOT $mirror "${scriptsdir}${FAIdistributionBase}"
cp /etc/resolv.conf $FAI_ROOT/etc/resolv.conf
# Now we can copy fstab
[ -f $fs ] && mv $fs $fs.old
cp -p $LOGDIR/fstab $fs
sendmon "TASKEND extrbase"
skiptask extrbase
goto-fai/00-copy-templates 0000755 0001750 0001750 00000000027 11346132434 015216 0 ustar benoit benoit #!/bin/sh
fcopy -ir /
goto-fai/prepareapt.DEFAULT 0000755 0001750 0001750 00000001573 11346132434 015270 0 ustar benoit benoit #!/bin/sh
sendmon "TASKBEGIN prepareapt"
# ftp and http needs resolv.conf in chroot environment, /etc/hosts is useful
# think about using fcopy for these two files
[ -f /etc/resolv.conf ] && cp /etc/resolv.conf $FAI_ROOT/etc
[ -f /etc/hosts ] && cp /etc/hosts $FAI_ROOT/etc
# set hostname in $FAI_ROOT
if [ -f /var/run/fai/FAI_INSTALLATION_IN_PROGRESS ]; then
echo $HOSTNAME >$FAI_ROOT/etc/hostname
if [ -n "$IPADDR" ]; then
ainsl -s $FAI_ROOT/etc/hosts "$IPADDR $HOSTNAME.$DOMAIN $HOSTNAME"
fi
fi
if [ X$FAI_ALLOW_UNSIGNED = X1 ]; then
cat <<-EOF > $FAI_ROOT/etc/apt/apt.conf.d/10fai
APT::Get::AllowUnauthenticated "true";
Aptitude::CmdLine::Ignore-Trust-Violations yes;
EOF
fi
# load generated sources.list
[ -f $FAI/files/etc/apt/sources.list/LAST ] && cp $FAI/files/etc/apt/sources.list/LAST $FAI_ROOT/etc/apt/sources.list
sendmon "TASKEND prepareapt"
skiptask prepareapt
goto-fai/error.DEFAULT 0000755 0001750 0001750 00000001171 11415400612 014241 0 ustar benoit benoit #!/bin/sh
# Show error message on first vt - force reboot after 10 minutes
# $1 = FAI error code
# $2 = error tester
# $3 = text
# $4, $5 = height width
# Skip default error task
skiptask error
# Skip debug parameter
[ $0 = "-d" ] && shift
[ "X$2" = "X0" ] && exit 0
[ $1 -lt $STOP_ON_ERROR ] && exit 0
[ "softupdate" = "$action" ] && exit 1
# We won't wait forever - reboot after 2 minutes
(sleep 120; faireboot) &
if [[ -n "$3" ]]; then
echo goto-error-fai:$1 / $3 >> $LOGDIR/fai.log
else
echo goto-error-fai:$1 >> $LOGDIR/fai.log
fi
echo TASKERROR $1 > /var/run/gosa-si/gosa-si-client.socket
goto-fai/confdir.DEFAULT.source 0000755 0001750 0001750 00000004557 11415400612 016046 0 ustar benoit benoit #!/bin/sh
# Debug Shell
[ "$debug" ] && openvt -v -- sh
# Anyone logged in?
logged=$(w -hs | wc -l)
# Let us define the hostname if hook is defined
if [ -x $FAI/hooks/hostname ]; then
$FAI/hooks/hostname
export HOSTNAME=$(cat /tmp/hostname)
hostname $HOSTNAME
fi
if [ $logged -eq 0 ]; then
# Always open new VT, but don't switch to it
#
# Some explanation, since we can't comment in this "script"
# - first setup environment
# - echo -ne "\033%G" sets UTF-8
#
FAI_PROGRESS_VT=$(openvt -v 2>&1 -- sh -c "
export TERM=linux ;
export TERM_UTF8=yes ;
export FAI_LOG_PATH=$LOGDIR/fai.log ;
[ -f /etc/default/locale ] && eval $(echo -n "export "; grep ^LANG /etc/default/locale) ;
if [ -c /dev/fb0 ]; then
export DEBIAN_FRONTEND=gtk ;
else
export DEBIAN_FRONTEND=newt ;
fi ;
echo -ne '\033%G' ;
setterm -blank 0 -powersave off -powerdown 0 ;
touch -f $LOGDIR/fai.log ;
/usr/lib/cdebconf/debconf /usr/bin/fai-progress ;
reset")
export FAI_PROGRESS_VT=${FAI_PROGRESS_VT##* }
echo "${FAI_PROGRESS_VT##/dev/tty}" > $LOGDIR/fai-progress-vt
fi
# Redefine sendmon in order to get the progress bar and GOsa-SI
# informed
unset sendmon
sendmon() {
# Send message to gosa-si-client
echo $* >> /var/run/gosa-si/gosa-si-client.socket &
}
if [ "$action" != "softupdate" ]; then
if [ $logged -eq 0 -a ! -c /dev/fb0 ]; then
# newt cdebconf frontend needs a chvt
chvt ${FAI_PROGRESS_VT##/dev/tty}
fi
else
# Check the dhclient lease file for the server-name to set SERVER
LEASE=$(ps ax | grep "dhclient" | grep -v "grep" | sed -n 's/.*-lf \([^ ]*\).*/\1/p')
if [ -f $LEASE ]; then
SERVER=$(cat $LEASE | sed -n 's/.*server-name "\([^"]*\)";$/\1/p')
fi
fi
# Rebase FAI to load the LDAP stuff later on
FAI_REBASE=$(mktemp -d "/tmp/fai-ldap-XXXXXX")
export FAI_CONFIG_SRC="gosa://${FAI_REBASE}"
# Copy error hook to make it available in the target system
mkdir -p "$FAI_REBASE/hooks"
mkdir -p "$FAI_REBASE/scripts/DEFAULT"
cp "$FAI/hooks/error.DEFAULT" "$FAI_REBASE/hooks"
cp "$FAI/hooks/extrbase.DEFAULT" "$FAI_REBASE/hooks"
cp "$FAI/hooks/prepareapt.DEFAULT" "$FAI_REBASE/hooks"
cp "$FAI/scripts/DEFAULT/00-copy-templates" "$FAI_REBASE/scripts/DEFAULT"
# Make fai rebase
export FAI="$FAI_REBASE"