Benutzer:Kirmse/Qotakontrolle

Aus Delixs
Zur Navigation springen Zur Suche springen

Es werden hier nur die Quotas der Schüler aus diesem Raum angezeigt. Dazu wird smbstatus aufgerufen, wodurch man alle Anmeldungen hat (Login, IP und Rechnernamen). Dann werden aus dem LDAP alle Rechner dieses Raumes geholt und mit diesen Anmeldungen abgeglichen und man erhält alle Logins von Schülern aus diesem Raum.

Dann werden die Quota-Daten von von diesen Schülern angezeigt. Schüler, bei denen für die "Grace Period" etwas steht, werden rot hervorgehoben. Schüler bei denen in "Grace Period" none steht, werden fett und rot hervorgehoben.

<source lang="perl">

  1. !/usr/bin/perl

use warnings; use strict;

use CGI::Carp qw(fatalsToBrowser); use Net::LDAP;

my ($teacher, $ip, @daten, $date, $room, %pcs, @smbstatus_output, @daten2,

   $partition, $platz, $soft1, $hard1, $soft2, $hard2, $special, %schueler,
   @liste, $login, $table);
  1. ========================== Konfigurationsbereich ========================
  1. hier können sie das Format fuer das Datum und die Uhrzeit angeben. Die
  2. Platzhalter %%tag%%, %%monat%%, %%jahr%%, %%stunde%%, %%minute%%, %%sekunden%%
  3. werden durch aktuellen Werte ersetzt, wobei alle Werte der Zeit zweistellig sind
  4. durch das vorgegebene Format entsteht z.B. "1.1.2008 13:41:05"

my $format = '%%tag%%.%%monat%%.%%jahr%% %%stunde%%:%%minute%%:%%sekunden%%';

  1. ========================== HTML-Bereich =================================
  1. Die generierte HTML-Seite wird zusammengesetzt aus dem Kopf, der (eigentlichen)
  2. Tabelle und dem Fuss. Hier wird die Variable $head als HERE-Dokument bereitgestellt.
  3. Ab der 2. Zeile, die mit: "<!doctype html ..." beginnt, ist alles reines HTML.
  4. Sie können damit ohne Perlkenntnisse das Aussehen der Seite beeinflussen.
  5. Beachten Sie, dass %%aufrufer%%, "%%rechner%%", "%%raum%% und %%datum%% durch
  6. das Script durch die aktuellen Werte ersetzt werden

my $head =<<'KOPF'; <!doctype html public "-//W3C//DTD HTML 4.0 //EN"> <html> <head> <title>Quotakontrolle</title> <meta name="author" content="Hans-Dietrich Kirmse"> <style type="text/css"> </style> </head> <body background="/online/whttxtr2.jpg" text="#000000" bgcolor="#FFFFFF" link="#0000FF" alink="#0000C0" vlink="#FF0000">

%%aufrufer%% am PC "%%rechner%%" im Raum "%%raum%%" %%datum%%

Quota-Situation für die Schüler dieses Raumes


Quotas für Device %%partition%%   - %%hd%% der Partition belegt

Für die Größe des Homeverzeichnisses eines jeden Schülers beträgt das Softlimit %%soft1%%kByte und das Hardlimit %%hard1%%kByte.
Für die Anzahl der Dateien im Homeverzeichnis eines jeden Schülers beträgt das Softlimit %%soft2%% und das Hardlimit %%hard2%%.

KOPF
  1. die Variable $foot sollte normalerweise nicht geändert werden, da nur Copyrightvermerk.
  2. Falls dieser an irgendeiner anderen Stelle erscheint, ist dagegen natürlich nichts einzuwenden.
my $foot =<<'FUSS';
User kByte Grace period 1 Dateien Grace period 2

© <a href="mailto:hd.kirmse@gmx.de">HD. Kirmse</a>   ERG Saalfeld/Thüringen, quota.cgi Version 0.2 - Oktober 2008

</body> </html> FUSS


  1. ========================== Hauptprogramm ================================
  1. wir holen uns das Login des Lehrers, von dem das Script aufgerufen wurde

$teacher = $ENV{REMOTE_USER}; defined($teacher) or die "es liegt keine Anmeldung am Apache vor, $!\n";

  1. wir holen uns die IP des Rechners, von dem das Script aufgerufen wurde

$ip = $ENV{REMOTE_ADDR}; defined($ip) or die "ein unerwarteter Fehler ist aufgetreten, $!\n";

  1. wir holen uns erstmal die Daten

@daten = `/usr/sbin/repquota -avug`; # unter UserID laufen lassen

  1. wir holen uns die Partiton

$partition = &get_partition(@daten);

  1. wir ermitteln den verwendeten Platz von /home

$platz = &verwendeter_platz_von_home;

  1. wir holen uns den Raum und die Rechner fuer diesen Raum

($room, %pcs) = &get_pcs; # %pcs: Key ist die IP, Value der Name

  1. wir rufen smbstatus auf -> IPs, Namen

@smbstatus_output = `smbstatus`; chomp(@smbstatus_output);

  1. jetzt erzeugen wir die Daten zur Bearbeitung von den aktuell angemeldeten PCs.
  2. uns interessieren von @output nur Zeilen, wo am Ende eine Klammer mit der IP ist
  3. Die Daten haben folgende Struktur: $daten[x] = \($ip, $login, $gruppe, $rechner);

@daten2 = &get_data(@smbstatus_output);

  1. wir reduzieren jetzt (anhand der IP) die Daten auf die Anmeldungen im Raum

@daten2 = &filtern_nach_raum(\@daten2, \%pcs);

  1. wir holen uns die Schüler aus diesen Raum und stecken die in einen Hash

%schueler = &hole_schueler(@daten2);

  1. wir holen von einem diese Namen (Login) die Werte für Soft- und Hardlimit
  2. für Dateien und Anzahl der Dateien (als Info über der Tabelle)

$special = &hole_einen_schueler(%schueler); ($soft1, $hard1, $soft2, $hard2) = &get_limits($special, @daten);

  1. jetzt holen wir uns die Daten fuer die Schueler dieses Raumes

foreach my $zeile (@daten) {

 # wenn es eine "relevante" Datenzeile ist
 if ($zeile =~ m/^(\w+)\s*[+|-]{2,2}/i) {
   # dann ueberpruefen wir, ob es ein User des Raumes ist
   $login = $1;
   if ( exists($schueler{$login}) ) {
     push @liste, $zeile;
   }
 }

}

  1. wir sortieren die Liste

@liste = sort @liste;

  1. dann werden für alle User die Daten angezeigt.
  2. wo bei Grace Period etwas steht, da wird rot gefärbt
  3. wo 'none' steht, wird der Name fett und rot dargestellt

$table = &baue_tabelle(@liste);

  1. wir holen uns Datum und Uhrzeit (wird im Kopf der HTML-Seite angezeigt)

$date = &datum($format);

  1. wir bearbeiten den Kopf

$head =~ s/%%aufrufer%%/$teacher/; $head =~ s/%%datum%%/$date/; $head =~ s/%%rechner%%/$pcs{$ip}/; $head =~ s/%%raum%%/$room/; $head =~ s/%%partition%%/$partition/; $head =~ s/%%hd%%/$platz/; $head =~ s/%%soft1%%/$soft1/; $head =~ s/%%hard1%%/$hard1/; $head =~ s/%%soft2%%/$soft2/; $head =~ s/%%hard2%%/$hard2/;

  1. wir schicken die Seite zum Apache

print "Content-type: text/html\n\n"; print $head; print $table; print $foot;

                          1. Ende des Hauptprogramms ###############################


sub get_pcs {

 my $ip = shift;
 my ($ldap_base, $ldap, $mesg, $entry, $dn, $pc, $suchbasis, %rechner,
     $tmp, $raum);
 # wir verbinden uns mit den LDAP
 $ldap = Net::LDAP->new('127.0.0.1',version => 3) or die "$@";
 $ldap->bind or die "konnte mich nicht mit dem Server verbinden";
 # wir holen uns die Suchbasis
 $ldap_base = &_get_ldapbase;
 # wir holen uns den Raum zu der IP ($ip)
 $mesg = $ldap->search(
            base   => "cn=DHCP Service Config,o=DHCP,$ldap_base",
            filter => "dhcpStatements=fixed-address $ip",
            attrs  => [ 'dhcpHost' ],
            scope  => "base");
 mesg->code and die $mesg->error;
 # wir holen uns den DN
 ($entry) = $mesg->entries or die "konnte keinen dhcpHost finden";
 $dn    = $entry->dn;
 # wir spalten vom DN den Rechnernamen ab, den Rest nehmen wir gleich als Suchbasis
 ($pc, $suchbasis) = $dn =~ /^cn=([^,]*),(.*)$/;
 # wir holen uns die Rechner (sind im DN) und IPs zu diesen Raum
 $mesg = $ldap->search(
            base => $suchbasis,
            filter => "objectClass=dhcpHost",
            attrs  => [ 'dhcpStatements' ]);
 $mesg->code and die $mesg->error;
 # wir trennen uns vom LDAP
 $ldap->unbind;
 # wir stecken die Daten aus den Entries in einen "normalen" Hash
 %rechner = ();
 foreach my $entry ($mesg->entries) {
   $dn   = $entry->dn;
   ($pc) = $dn  =~ /^cn=([^,]*),/ ;   # die Klammer ist der Rechnername
   $tmp  = $entry->get_value('dhcpStatements');
   ($ip) = $tmp =~ /fixed-address (.*)$/;
   $rechner{$ip} = $pc;
 }
 # wir holen uns noch den Raum
 ($raum) = $suchbasis =~ /^cn=([^,]*),/ ; # die Klammer ist der Raum
 return ($raum,%pc);

}


  1. --------------------------------------------------------------------
  2. Funktion: Hilfsfunktion zur zweistelligen Darstellung der Zeitdaten
  3. Aufruf: $sek = &zweistellig($sek);
  4. Input: $sek oder $min oder $std
  5. Output: diese Werte, aber zweistellig
  6. Update: 1.01.2008
  7. --------------------------------------------------------------------

sub zweistellig {

 my $datum = shift;
 if ($datum < 10) { $datum = '0'.$datum }
 return $datum;

}


  1. --------------------------------------------------------------------
  2. Funktion: liefert formatierten Datumsstring
  3. Aufruf: $date = &datum($format);
  4. Input: String fuer das Ausgabeformat
  5. Output: String mit Datum und Uhrzeit
  6. Update: 1.01.2008
  7. --------------------------------------------------------------------

sub datum {

 my $format = shift;
 my @date  = localtime();
 my $sek   = $date[0];
 my $min   = $date[1];
 my $std   = $date[2];
 my $tag   = $date[3];
 my $monat = $date[4] + 1;
 my $jahr  = $date[5] + 1900;
 $sek = &zweistellig($sek);
 $min = &zweistellig($min);
 $std = &zweistellig($std);
 my $rueckgabe = $format;
 $rueckgabe =~ s/%%tag%%/$tag/;
 $rueckgabe =~ s/%%monat%%/$monat/;
 $rueckgabe =~ s/%%jahr%%/$jahr/;
 $rueckgabe =~ s/%%stunde%%/$std/;
 $rueckgabe =~ s/%%minute%%/$min/;
 $rueckgabe =~ s/%%sekunden%%/$sek/;
 return $rueckgabe;

}


  1. --------------------------------------------------------------------
  2. Funktion: aus der Ausgabe von smbstatus werden die Daten herausgezogen
  3. Aufruf: @daten = &get_data(@output);
  4. Input: @output = die Ausgabe von smbstatus
  5. Output: $daten[x] = \($ip, $login, $gruppe, $rechner);
  6. Update: 13.08.2007
  7. --------------------------------------------------------------------

sub get_data {

 my @output = @_;
 my @daten = ();
 foreach my $zeile (@output) {
   if ($zeile =~ /^
                    \d+\s*                         # die PID
                   (\w+)\s*                        # der User (login) = $1
                   (\w+)\s*                        # die Gruppe       = $2
                   (\w+)\s*                        # der Rechnername  = $3
                   \((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)  # die IP = $4
                 $/x) {
     my @values = ( $4, $1, $2, $3 );    # wird eine anonyme Liste
     push @daten, \@values;
   }
 }
 return @daten;

}


  1. --------------------------------------------------------------------
  2. Funktion: es werden nur die Datensaetze aus diesem Raum zurueckgegeben
  3. Aufruf: @daten = &filtern_nach_raum(\@daten, \%pcs);
  4. Input: $daten[x] = \($ip, $login, $gruppe, $rechner);
  5. $pcs{$ip} = $rechnername;
  6. Output: $daten[x] = \($ip, $login, $gruppe, $rechner);
  7. Update: 16.12.2007
  8. --------------------------------------------------------------------

sub filtern_nach_raum {

 my $lref_daten = shift;
 my $href_pcs   = shift;
 my @daten = @{$lref_daten};
 my %pcs   = %{$href_pcs};
 my ($ip, @temp);
 foreach my $nr (@daten) {
   my @liste = @{$nr};
   # wir holen uns die IP
   $ip = $liste[0];
   # nur wenn diese IP zu den Rechnern des Raumes gehoert
   if (defined($pcs{$ip})) {
     # dann wollen wir diesen Datensatz
     push @temp, \@liste;
   }
 }
 return @temp;

}


  1. diese Funktion geht davon aus, dass es nur eine Partition mit Quotas gibt!

sub get_partition {

 my @daten = @_;
 my $partition = ;
 foreach my $zeile (@daten) {
   # wenn die Zeile am Anfang "*** Report for" enthaelt, holen wir die Partition
   if ($zeile =~ m/^\*\*\* Report for.* (\/dev\/.*)/i) {
     $partition = $1;
     # und brechen ab
     last;
   }
 }
 return $partition;

}


sub verwendeter_platz_von_home {

 my @temp = `/bin/df`;
 my $used;
 foreach my $zeile (@temp) {
   if ($zeile =~ /\s+(\d+%)\s+\/home$/) {
      $used = $1
   }
 }
 return $used

}


sub hole_schueler {

 my @daten = @_;
 my (@temp, $login);
 my %schueler = ();
 foreach my $datum (@daten) {
   @temp = @{$datum};  # $daten[x] = \($ip, $login, $gruppe, $rechner);
   # nur wenn die Gruppe 'schueler' ist
   if ($temp[2] eq 'schueler') {
     # dann wollen wir das Login
     $login = $temp[1];
     # und stecken das in den Hash %schueler
     $schueler{$login} = 1;
   }
 }
 return %schueler;

}


sub hole_einen_schueler {

 my %schueler = @_;
 my @schueler = keys %schueler;
 # wir nehmen einfach den ersten Key
 return $schueler[0];

}


sub get_limits {

 my $schueler = shift;
 my @daten = @_;
 my @temp;
 foreach my $zeile (@daten) {
   if ($zeile =~ /^$schueler/) {
     @temp = split /\s+/, $zeile;
     last;
   }
 }
 # soft1, hard1, soft2, hard2;
 return ($temp[3], $temp[4], $temp[6], $temp[7]);

}


sub baue_tabelle {

 my @liste   = @_;
 my $tabelle = ;
 if (scalar @liste > 0) {
   # fuer jede Zeile von @liste
   foreach my $zeile (@liste) {
     # wir holen uns die einzelnen Elemente fuer die Tabelle
     $zeile =~ m/^                            # am Anfang
                (\w+)                         # mindestens ein Buchstabe (Login) $1
                 \s*                          # keins oder mehrere Whitespace
                ([-|+])                       # ein + oder ein -                 $2
                ([-|+])                       # ein + oder ein -                 $3
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $4
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $5
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $6
                 \s+                          # mindestens ein Whitespace
                ([\w|:]*)                     # keins, mehrere Buchstaben, ":"   $7
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $8
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $9
                 \s+                          # mindestens ein Whitespace
                (\d+)                         # mindestens eine Ziffern          $10
                 \s+                          # mindestens ein Whitespace
                ([\w|:]*)                     # keins, mehrere Buchstaben, ":"   $11
                     /ix ;                    # i = ignoriere Groß- / Kleinschreibung
                                              # x = Kommentare im reg. Ausdr. erlaubt
     my $temp1 = $7;                          # hier geht es nur darum, dass leere
     my $temp2 = $11;                         # Tabellenzellen trotzdem richtig
     # alle Logins, bei denen nichts mehr geht, sind fett und rot hervorgehoben
     my $account = $1;
     if ($temp1 eq 'none' or $temp2 eq 'none') {
       $account = ''.$account.'';
     }
     # alle Accounts, bei denen die Grace Period nicht leer ist, werden rot gefaerbt
     elsif ($temp1 ne  or $temp2 ne ) {
       $account = ''.$account.'';
     }
     if ($temp1 eq ) { $temp1 = ' ' };  # damit Tabelle ordentlich dargestellt
     if ($temp2 eq ) { $temp2 = ' ' };  # werden kann ->  

$tabelle .= ''.$account.''; $tabelle .= ''.$4.''; $tabelle .= ''.$temp1.''; $tabelle .= ''.$8.''; $tabelle .= ''.$temp2.''; $tabelle .= ''."\n"; } } return $tabelle; } __END__ </source>


Benutzer:Kirmse