#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Std;
use Socket;
use Net::LDAP; # From libnet-ldap-perl debian package
use SiteSummary;

my $debug = 0;

my $server = "ldap";
my $base = "dc=skole,dc=skolelinux,dc=no";

my $binddn = "cn=admin,ou=People,$base";
my $bindpw = "";

sub usage {
    my $retval = shift;
    print <<EOF;
sitesummary2ldap
Add machine objects to LDAP based on sitesummary information.

 -d             Enable debug output.
 -i ID          Handle host with the given sitesummary ID only.

EOF
    exit $retval;
}

my %opts;
my $retval = 0;

getopts("di:", \%opts) || usage(1);
$debug = 1 if $opts{d};

my $ldap = Net::LDAP->new( $server ) or die "$@";
$ldap->start_tls();
my $mesg = $ldap->bind($binddn, password => $bindpw);
die "Unable to bind to LDAP server: " . $mesg->error if $mesg->code;

if ($opts{i}) {
    host_handler($opts{i});
} else {
    for_all_hosts(\&host_handler);
}
$mesg = $ldap->unbind;
exit $retval;


sub host_handler {
    my $hostid = shift;
    my $ipaddr = SiteSummary::get_primary_ip_address($hostid);
    my $fqdn = scalar gethostbyaddr(inet_aton($ipaddr), AF_INET);
    my $macref = [(get_ether_hwaddr($hostid))];
    if ($fqdn) {
        my $hostcn = host_cn($ldap, $fqdn, $macref);
        if (!$hostcn) {
            add_machine($ldap, $fqdn, $ipaddr, $macref);
        } else {
            # Update
        }
    }
}

sub get_ether_hwaddr {
    my $hostid = shift;
    my $path = get_filepath_current($hostid, "/system/ifconfig-a");
    if (open(FILE, "<", $path)) {
        my $sysinfo = 0;
        my @hwaddr = ();
        while (<FILE>) {
            chomp;
            if (m/Link encap:Ethernet  HWaddr (.+\S)\s*$/) {
                push(@hwaddr, $1);
            }
        }
        close(FILE);
        return @hwaddr;
    } else {
        return undef;
    }
}

# See if host already exist in LDAP
sub host_cn {
    my($ldap, $fqdn, $macref) = @_;
    return undef;
}

sub generate_host_cn {
    my ($ldap, $base, $hostname, $fqdn) = @_;
    my $dn = "cn=$hostname,ou=Machines,ou=People,$base";
    return $dn;
}

sub add_machine {
    my ($ldap, $fqdn, $ipaddr, $macref) = @_;

    my @macaddr = @{$macref};
    my ($hostname, $dnsdomain) = split(/\./, $fqdn, 2);

    my $cn = generate_host_cn($ldap, $base, $hostname, $fqdn);
    my @hwaddr = map { "ethernet $_"; } @macaddr;

    my $attr = [
                'cn'               => $hostname,
                'associatedDomain' => $dnsdomain,
                'ipHostNumber'     => $ipaddr,
                'macAddress'       => (@macaddr)[0], #XXX How to handle more?
# Combined DHCP/LWAT objects did not work
#                'dhcpHWAddress'    => (@hwaddr)[0],
#                'dhcpStatements'   => "fixed-address $fqdn",

# hw vendor, model, serial number?
                'objectclass' => ['top',
                                  'organizationalRole',
                                  'domainRelatedObject',
                                  'ipHost',
                                  'ieee802Device',
#                                  'dhcpHost',
                                  ],
                ];
    # XXX This fail with
    # "invalid structural object class chain (organizationalRole/dhcpHost)"
    my $result = $ldap->add($cn, attr => $attr);
    $result->code && die $result->error;
}
