goto-fai/0000755000175000017500000000000011415400612012077 5ustar benoitbenoitgoto-fai/ldap2fai0000755000175000017500000003765211415400612013524 0ustar benoitbenoit#!/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-loc0000755000175000017500000000021711346132434014271 0ustar benoitbenoit#!/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-softupdate0000755000175000017500000000053011346132434014745 0ustar benoitbenoit#!/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.10000644000175000017500000001247111415400612013650 0ustar benoitbenoit.\" 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-gosa0000755000175000017500000000451311415400612015555 0ustar benoitbenoit#!/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.DEFAULT0000755000175000017500000000216211415400612014726 0ustar benoitbenoit#!/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-templates0000755000175000017500000000002711346132434015216 0ustar benoitbenoit#!/bin/sh fcopy -ir / goto-fai/prepareapt.DEFAULT0000755000175000017500000000157311346132434015270 0ustar benoitbenoit#!/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.DEFAULT0000755000175000017500000000117111415400612014241 0ustar benoitbenoit#!/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.source0000755000175000017500000000455711415400612016046 0ustar benoitbenoit#!/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"