Automatisk innlegging av MAC-adresser i Lenny

Petter Reinholdtsen <[email protected]> Fri, 16 Jul 2010 01:02:03 +0200
Newsgroups gmane.linux.skolelinux.bruker
Message-ID <[email protected]>
I Skolelinux blir informasjon om maskinene samlet inn automatisk av et
system som heter sitesummary.  Denne informasjonen blir brukt til å
sette opp Nagios-overvåkning og Munin-grafing, men den kan brukes til
mye mer.

De siste timene har jeg frisket opp en liten programsnutt jeg startet
på for lenge siden, for å oppdatere informasjon om maskinene i LDAP.
I Lenny blir DHCP-informasjonen hentet fra LDAP, og scriptet under
oppdaterer MAC-adressen i DHCP-oppsettet slik at alle maskinene som er
registrert får fast adresse fra DHCP-tjeneren.

Fungerer scriptet for deg?  Det gjenstår en god del før det er ferdig
(ønsker å oppdater DNS-info og sikre at kun en DHCP-oppføring for en
gitt MAC-adresse eksiterer), men skulle være nyttig allerede i dag.

#!/usr/bin/perl

use strict;
use warnings;

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

my $debug = 0;

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

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

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();
print "Connecting to LDAP as $binddn\n";
my $bindpw = prompt('enter password: ', -echo => '*');

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) {
        add_or_update_machine($ldap, $fqdn, $ipaddr, $macref);
    } else {
        print "warning: Not registring entry $hostid, missing in DNS.\n";
    }
}

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;
    }
}

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

    my $mac = (@{$macref})[0], # FIXME How to handle several MAC addresses?
    my ($hostname, $dnsdomain) = split(/\./, $fqdn, 2);

    my $cn = "cn=$hostname,cn=group1,cn=INTERNAL,cn=DHCP Config,$base";

    my $mesg = $ldap->search(
        base   => $cn,
        filter => '(objectClass=dhcpHost)'
        );

    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);
        $result->code && die $result->error;
    } elsif (1 == $mesg->count) {
        # Update

        foreach my $entry ($mesg->all_entries) {
            $entry->dump if $debug;
            $entry->replace(
                'dhcpHWAddress'  => "ethernet $mac",
                'dhcpStatements' => "fixed-address $fqdn"
                );
            $entry->update($ldap);
        }
    } else {
        print STDERR "error: Not sure how to handle this\n";
    }
}

sub add_or_update_machine {
    my ($ldap, $fqdn, $ipaddr, $macref) = @_;
    print "Updating host entry for $fqdn\n" if $debug;
    add_or_update_dhcp($ldap, $fqdn, $ipaddr, $macref);
}

# Fetched from <URL: http://www.perlmonks.org/?node_id=553981 >.
sub prompt {
    my ($prompt, %args) = @_;
    local $| = 1;
    my $phrase = '';
    print $prompt;
    ReadMode 'cbreak';
    while (1) {
        my $c = ReadKey ~0/2-1; #windows workaround http://rt.cpan.org/Public/Bug/Display.html?id=27944
        if ($c =~ /[\r\n]/) {
            print "\n";
            last;
        }
        elsif ($c eq "\b" || ord $c == 127) {
            next unless length $phrase;
            chop $phrase;
            next if !defined $args{-echo};
            print map $_ x length $args{-echo}, "\b", " ", "\b";
        }
        elsif (ord $c) {
            $phrase .= $c;
            print $args{-echo} if defined $args{-echo};
        }
    }
    ReadMode 'restore';
    $phrase;
}

Vennlig hilsen,
-- 
Petter Reinholdtsen

-- 
For å melde deg av denne epostlisten eller endre innstillingene dine besøk:
https://init.linpro.no/mailman/skolelinux.no/listinfo/bruker