#!/usr/bin/perl -w
#
# "SystemImager"
#
#  Copyright (C) 2002 Bald Guy Software 
#                     Brian E. Finley <brian.finley@baldguysoftware.com>
#  Copyright (C) 2003 Brian E. Finley <finley@mcs.anl.gov>
#
#    $Id: si_netbootmond 4366 2007-12-14 12:04:27Z arighi $
#
#    2005.07.12 Brian Elliott Finley
#    - apply umask patch for Daniel Widyono
#

use lib "/usr/lib/systemimager/perl";
use strict;
use File::Copy;
use POSIX qw(setsid);
use SystemImager::Config;
use SystemImager::HostRange;
use SystemImager::Server;
use vars qw($config $VERSION);

$0 = "si_netbootmond";

my $net_boot_default = lc $config->net_boot_default();
if("$net_boot_default" eq "net") {
    print STDERR qq(\nNET_BOOT_DEFAULT set to "$net_boot_default" in /etc/systemimager/systemimager.conf.\n);
    print STDERR qq(No need for me here, so I'm exiting. See si_netbootmond\(8\) for details.\n);
    exit 0;
}

my $tftp_dir = $config->tftp_dir();
my $pxe_conf_dir;
my $kboot_conf_dir;

unless($tftp_dir) {
    die "FATAL: parameter TFTP_DIR is not defined in /etc/systemimager/systemimager.conf\n";
} else {
    $pxe_conf_dir = "$tftp_dir" . "/pxelinux.cfg";
    $kboot_conf_dir = "$tftp_dir" . "/kboot.cfg";
}

my $syslinux_cfg_localboot = "/etc/systemimager/pxelinux.cfg/syslinux.cfg.localboot";
my $kboot_cfg_localboot = "/etc/systemimager/kboot.cfg/localboot";
my $pid_file = "/var/run/si_netbootmond.pid";
my $log_file = "/var/log/systemimager/rsyncd";


################################################################################
#
# Misc. Daemon stuff
#
################################################################################
chdir '/'                   or die "Can't chdir to /: $!";
open STDIN, '/dev/null'     or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null'  or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null'  or die "Can't write to /dev/null: $!";
umask 0;
sub REAPER {
    $SIG{CHLD} = \&REAPER;
    my $waitedpid = wait;
    print STDERR "Dead child: $waitedpid\n";
}
$SIG{CHLD} = \&REAPER;


################################################################################
#
# Fork the watching process
#
################################################################################
my $pid;
if ($pid = fork) {
} elsif (defined $pid) { # send the forked child off

    setsid or die "Can't start a new session: $!";

    my $file = $pid_file;
    local *FILE;
    open(FILE,">$file") or die ("FATAL: Can't open file: $file\n");
        print FILE "$$\n";
    close(FILE);

    # Lurk
    tail_rsync_log_file();

} else {
        die "Can't fork: $!\n";
}


################################################################################
#
# BEGIN subroutines 
#
sub tail_rsync_log_file {

    my $pid;

    $SIG{TERM} = sub {
        if (defined($pid)) {
            kill(1, $pid);
        }
    };

    my $cmd = "tail -n 0 --follow=name $log_file";
    local *LOG_FILE;
    $pid = open(LOG_FILE,"$cmd |") || die("Can't $cmd!");
        while(<LOG_FILE>) {
       
            # Get individual field values for this line
            my @array = split(/\s+/);

            if ($array[5] =~ /scripts\/imaging_complete_?([\.0-9]+)?/) {

                my $client_ip;

                if (defined($1)) {
                    $client_ip = $1;
                } else {
                    $client_ip = $array[8];
                    $client_ip =~ s/\(//g;
                    $client_ip =~ s/\)//g;
                }

                # diagnostic output
                #print "Configuring $client_ip for local booting.\n";
                create_no_boot_symlink($client_ip);
            }
        }
    close(LOG_FILE);
    exit 0;
}


# Usage: create_no_boot_symlink($client_ip);
sub create_no_boot_symlink {

    my ($client_ip) = @_;

    my $ip_hex = SystemImager::HostRange::ip2hex($client_ip);
    my $conf_dir;
    my $localboot_file;

    if (-d $kboot_conf_dir) {
        $conf_dir = $kboot_conf_dir;
        $localboot_file = $kboot_cfg_localboot;
    } else {
        $conf_dir = $pxe_conf_dir;
        $localboot_file = $syslinux_cfg_localboot;
    }

    # Diagnostic output
    #print "ip_hex: $ip_hex\n";

    unlink("$conf_dir/$ip_hex");
    umask(0022);
    copy("$localboot_file", "$conf_dir/$ip_hex");
    
}
#
# END subroutines
#
################################################################################

__END__

=head1 NAME

si_netbootmond - SystemImager's daemon for controlling netboot clients.

=head1 SYNOPSIS

/etc/init.d/systemimager-server-netbootmond start|stop|status|restart

=head1 DESCRIPTION

If clients are configured to always boot from the network, B<si_netbootmond> can
be configured to tell them to boot off their local disks each time they boot
after having completed a successful autoinstall.

This allows to always set network booting as default from the BIOS of the
clients and boot from local disk after a successfull auto-installation.

To enable this feature the parameter B<NET_BOOT_DEFAULT> must be set to B<net>
in B</etc/systemimager/systemimager.conf> and si_netbootmond must be started via
the init script B</etc/init.d/systemimager-server-netbootmond>.

To disable this feature set B<NET_BOOT_DEFAULT> to B<local> in
B</etc/systemimager/systemimager.conf> or just stop B<si_netbootmond> via the
init script B</etc/init.d/systemimager-server-netbootmond>.

=head1 SEE ALSO

systemimager(8), si_mkclientnetboot(8), /etc/init.d/systemimager-server-netbootmond

=head1 AUTHOR

Brian E. Finley <finley@mcs.anl.gov>.

=head1 COPYRIGHT AND LICENSE

Copyright 2002-2003 by Brian E. Finley <finley@mcs.anl.gov>.

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.

=cut

