#!/usr/bin/perl use strict; use warnings; use Getopt::Std; use Socket; use Net::LDAP; # From libnet-ldap-perl debian package use SiteSummary; use Debian::Edu qw(prompt4password find_ldap_server find_ldap_base); my $debug = 0; my %opts; getopts("adi:u:t:", \%opts) || usage(1); $debug = 1 if $opts{d}; my $server = $ARGV[0] || find_ldap_server() || "ldap"; my $base = $ARGV[1] || find_ldap_base($server) || "dc=skole,dc=skolelinux,dc=no"; my $type = "workstations"; if ($opts{t}) { $type = $opts{t} } my $systembase = "ou=$type,ou=systems,$base"; my $dhcpbase = "cn=dhcp,cn=tjener,ou=servers,ou=systems,$base"; my $userfilter = $opts{u} || "(cn=admin)"; sub usage { my $retval = shift; print <new( $server ) or die "$@"; $ldap->start_tls(); my $binddn = (find_ldap_objects($ldap, $userfilter))[0]->dn(); print "\nEnter password if you want to activate these changes, and ^c to abort.\n\n"; print "Connecting to LDAP as $binddn\n"; my $bindpw = prompt4password('enter password: ', -echo => '*'); my $mesg = $ldap->bind($binddn, password => $bindpw); die "Unable to bind to LDAP server: " . $mesg->error if $mesg->code; for my $hostid (keys %hostinfo) { my ($fqdn, $ipaddr, $macref, $usedhcp) = @{$hostinfo{$hostid}}; add_or_update_machine($ldap, $fqdn, $ipaddr, $macref, $usedhcp); } $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 = [(SiteSummary::get_macaddresses($hostid))]; # Update MAC and IP if name has been changed if ($fqdn && $fqdn !~ m/^auto-mac-/) { print "info: Updating machine $fqdn [$ipaddr] id $hostid.\n"; $hostinfo{$hostid} = [$fqdn, $ipaddr, $macref, 1]; } elsif ($opts{a}) { my $mac = get_primary_ether_hwaddr($macref); # Use -I 127.0.0.1 to disable DNS lookup $fqdn=`/usr/sbin/update-hostname-from-ip -m -I 127.0.0.1 -M $mac -n`; chomp $fqdn; print "info: Create GOsa machine for $fqdn [$ipaddr] id $hostid.\n"; $hostinfo{$hostid} = [$fqdn, $ipaddr, $macref, 0]; } else { print "info: Ignoring new machine [$ipaddr] id $hostid.\n"; } } sub get_primary_ether_hwaddr { # FIXME How to handle several MAC addresses? my $macref = shift; my $mac = (@{$macref})[0]; } sub find_ldap_objects { my ($ldap, $filter) = @_; my $mesg = $ldap->search( base => $base, filter => $filter, ); return $mesg->all_entries; } sub add_or_update_gosasystem { my ($ldap, $fqdn, $ipaddr, $macref) = @_; my $mac = get_primary_ether_hwaddr($macref); my ($hostname, $dnsdomain) = split(/\./, $fqdn, 2); my $cn = "cn=$hostname,$systembase"; my $mesg = $ldap->search( base => $base, filter => "(&(|(objectClass=goServer)(objectClass=device)(objectClass=GOhard)(objectClass=gotoWorkstation)(objectClass=gotoTerminal))(|(cn=$hostname)(macAddress=$mac)))", ); print "info: search found " . $mesg->count . " objects\n" if $debug; if (0 == $mesg->count) { # Create entry of type $type my $gotoMode = "active"; my $gotoSwapServer = "!"; my $gotoNtpServer = "ntp"; my $ghCpuType = "-"; my $ghMemSize = "-"; my $ghUsbSupport = "-"; my $ghGfxAdapter = "-"; my $ghSoundAdapter = "-"; my $gotoLastUser = "-"; my $attr; if ($type eq 'servers') { $attr = [ 'objectClass' => ['top', 'GOhard', 'goServer'], 'cn' => $hostname, 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, 'gotoMode' => $gotoMode, ]; } elsif ($type eq 'workstations') { $attr = [ 'objectClass' => ['top', 'gotoWorkstation', 'GOhard'], 'cn' => $hostname, 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, 'gotoMode' => $gotoMode, 'gotoNtpServer' => $gotoNtpServer, 'ghCpuType' => $ghCpuType, 'ghMemSize' => $ghMemSize, 'ghUsbSupport' => $ghUsbSupport, 'ghGfxAdapter' => $ghGfxAdapter, 'ghSoundAdapter' => $ghSoundAdapter, 'gotoLastUser' => $gotoLastUser, ]; } elsif ($type eq 'terminals') { $attr = [ 'objectClass' => ['top', 'gotoTerminal', 'GOhard'], 'cn' => $hostname, 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, 'gotoMode' => $gotoMode, 'gotoNtpServer' => $gotoNtpServer, 'ghCpuType' => $ghCpuType, 'ghMemSize' => $ghMemSize, 'ghUsbSupport' => $ghUsbSupport, 'ghGfxAdapter' => $ghGfxAdapter, 'ghSoundAdapter' => $ghSoundAdapter, 'gotoLastUser' => $gotoLastUser, 'gotoSwapServer' => $gotoSwapServer, ]; } elsif ($type eq 'printers') { my $printerUri = "DUMMY, please change."; $attr = [ 'objectClass' => ['top', 'gotoPrinter'], 'cn' => $hostname, 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, 'labeledURI' => $printerUri, ]; } elsif ($type eq 'netdevices') { $attr = [ 'objectClass' => ['top', 'device', 'ipHost', 'ieee802Device'], 'cn' => $hostname, 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, ]; } if ($attr) { my $result = $ldap->add($cn, attr => $attr); if ($result->code) { my $err = $result->error; print STDERR "error: Unable to add LDAP object $cn - $err\n"; } } else { print STDERR "error: Unknown type $type, not adding objects\n"; } } elsif (1 == $mesg->count) { # Update foreach my $entry ($mesg->all_entries) { $entry->dump if $debug; $entry->replace( 'macAddress' => $mac, 'ipHostNumber' => $ipaddr, ); my $result = $entry->update($ldap); if ($result->code) { my $err = $result->error; print STDERR "error: Unable to update LDAP object $cn - $err\n"; } } } else { print STDERR "error: Not sure how to handle several LDAP objects for the same host (mac=$mac)\n"; } } sub add_or_update_dhcp { my ($ldap, $fqdn, $ipaddr, $macref) = @_; my $mac = get_primary_ether_hwaddr($macref); my ($hostname, $dnsdomain) = split(/\./, $fqdn, 2); my $cn = "cn=$hostname,$dhcpbase"; my $mesg = $ldap->search( base => $base, filter => "(&(objectClass=dhcpHost)(cn=$hostname))" ); print "info: dhcpHost search found " . $mesg->count . " objects\n" if $debug; if (0 == $mesg->count) { # Create my $attr = [ 'objectClass' => 'dhcpHost', 'cn' => $hostname, 'dhcpHWAddress' => "ethernet $mac", 'dhcpStatements' => "fixed-address $fqdn" ]; my $result = $ldap->add($cn, attr => $attr); if ($result->code) { my $err = $result->error; print STDERR "error: Unable to add DHCP LDAP object $cn - $err\n"; } } elsif (1 == $mesg->count) { # Update foreach my $entry ($mesg->all_entries) { $entry->dump if $debug; $entry->replace( 'dhcpHWAddress' => "ethernet $mac", 'dhcpStatements' => "fixed-address $fqdn" ); my $result = $entry->update($ldap); if ($result->code) { my $err = $result->error; print STDERR "error: Unable to update DHCP LDAP object $cn - $err\n"; } } } else { print STDERR "error: Not sure how to handle this\n"; } } sub add_or_update_machine { my ($ldap, $fqdn, $ipaddr, $macref, $usedhcp) = @_; print "Updating host entry for $fqdn\n" if $debug; add_or_update_gosasystem($ldap, $fqdn, $ipaddr, $macref); if ($usedhcp) { add_or_update_dhcp($ldap, $fqdn, $ipaddr, $macref); } }