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