========================================================== Virtuelles Unix Labor - Design - Hubert Feyrer ========================================================== 0. Konventionen I:X:Y:Z: Interaktion X zu Y, laufende Nummer Z DB:X:Y: Datenbank, Tabelle X Spalte Y 1. Komponenten User | | v| User Management | / | \ u| / | \ | / | \ l| Kurs Engine --- Datenbank ---- Scheduler | | / \ | a| | / \ | | | / \ | b| Firewall Deployment 1. User 2. User Management (UM) 3. Kursengine (KE) 4. Scheduler (SC) 5. Datenbank (DB) 6. Firewall (FW) 7. Deployment (DE) 2. Aufgaben der Komponenten 2.1 User Student, der mittels Web-Browser, telnet/ssh und ftp übt. Neben Scheduler einzige und gleichzeitig wichtigste aktive "Komponente", liefert Steuerinformation, interagiert mit User-Management und Kursengine sowie natuerlich den Uebungsrechnern. 2.2 User Management & Buchungssystem Web-Frontend und Zugang zum Übungssystem, realisiert durch dynamische PHP-Scripte sowie statische HTML-Seiten. Benutzerverwaltung, Anmeldung fuer Kurse, Zugang zur Kursengine, Buchen von Uebungen, Deployment-Auftrag an Scheduler, Firewall freischalten vor Uebung Aufgaben: - Neuanmeldung: * Daten uebernehmen: Name, EMail-Adresse, Passwort * Daten in Datenbank ablegen I:UM:DB:1 [DB:benutzer:user_id, DB:benutzer:vorname, DB:benutzer:nachname, DB:benutzer:email, DB:benutzer:passwort, DB:benutzer:freischalt_secret] * Bestaetigung per Mail versenden, mit best. Link zum Bestaetigen; enthaelt eindeutiges Passwort zur Authentifizierung der Bestaetigung. [DB:benutzer:freischalt_secret] * User ist sofort eingeloggt, aber nicht freigeschaltet * Wenn User auf Link klickt(...) ist der Account offiziell freigeschaltet I:UM:DB:2 [DB:benutzer:freischalt_secret="bestaetigt"] - Login: * Mit Login & Passwort anmelden [DB:benutzer:email, DB:benutzer:passwort] * Wenn Account noch nicht bestaetigt, Meldung ausgeben und zum freischalten auffordern I:UM:DB:2 [XXX DB:benutzer:Freigeschaltet=ja] * Pruefen ob "normaler" User, Lehrer/Professor oder Admin ist [DB:benutzer:typ] * Auswahl, was tun: . Logout . Übung buchen (User/Admin only) . Übung einstellen (Prof/Admin only) . Üben (User only) . Auswertungen (User/Admin only) . Administration der Benutzerdaten (User/Admin) - Aufgabe buchen: * Aufgabe aussuchen I:UM:DB:3 Gesamtdauer := Vorlauf (Deployment) + übungsdauer + Nachlauf (Checks) [DB:uebung:uebung_id, DB:uebung:vorlauf, DB:uebung:dauer, DB:uebung:nachlauf] * Datum & Uhrzeit auswaehlen (Reihenfolge?!) * Abschicken * Ueberpruefen ob Labor zum Zeitpunkt frei [DB:buchungen:uebung_id, DB:buchungen:startzeit, DB:uebung:vorlauf, DB:uebung:dauer, DB:uebung:nachlauf] * Wenn nein, zurueck. * Uebung in DB buchen I:UM:DB:4 [DB:buchungen:freigegeben(user_id,uebung_id,startzeit) = "nein"] * at(1)-Job aufsetzen, der Labor vorbereitet (-> Deployment) "at gewuenschteZeit-Vorlauf setup DB:buchungen:buchungs_id" I:UM:SC:1 - Übung einstellen: (TODO) - Üben * Daten aus DB: User, gebuchte Kurse, wann+von wem gebucht I:UM:DB:5 [DB:buchungen:user_id==DB:benutzer:user_id, DB:buchungen:uebung_id, DB:buchungen:startzeit] * Wen Übung nicht gebucht: irgendwas ausgeben :) * Wenn Übung nicht vorbereitet: Anzeigen von gebuchten Termin(en) [DB:buchungen:freigegeben] * Uebergeben an Kursengine I:UM:KE:1 [DB:uebung:uebung_id, DB:benutzer:user_id, DB:buchungen:startzeit] - Auswertungen * Daten aus Datenbank auslesen I:UM:DB:6 [DB:buchungen:user_id==DB:benutzer:user_id] * Auflistung der Gesamt-Ergebnisse aller absolvierten Übungen * Details zu jeder Übung - Score pro Check [DB:ergebnis_checks:erfolg, ...] * Diverse statistische Auswertungen (Durschnitt, Zeit/Dauer, Verteilung pro Teilaufgabe, ...) [DB:buchungen:startzeit, DB:buchungen:endzeit, ...] 2.3 Kursengine Web-Frontend das die Übung steuert. Auf dem Übungs-Server des Virtuellen Unix Labors liegen HTML-Dateien, PHP-Scripten und IP-Filter, auf den einzelnen Uebungsrechnern sorgen diverse Daemonen (sshd, telnetd, ftpd) für den Ablauf der Übungen. Speichern von Übungen (Aufgabentext + Image), Präsentation von Übungsaufgaben, ggf. Unterstützung/Erklaerung, ggf. weiterfuehrender Text & Hintergrund, Anstossen der Auswertung, abspeichern der Ergebnisse in Datenbank Aufgaben: - Firewall aufmachen (vor Uebung) * IP-Nummer aus CGI uebernehmen (-> I:UM:KE:1) * Formular zum Anpassen der freizuschaltenden IP anbieten: IP-Nummer (Default: $HTTP_X_FORWARDED_FOR wenn gesetzt, ansonsten $REMOTE_ADDR, ggf. Anzahl Hostbits a'la CIDR zum Freischalten von Netzen (Default: /32 == 1 Host) * Firewall-Modul mit IP/hostbits aufrufen I:KE:FW:1 * Daten zum entfernen in Datenbank hinterlegen I:KE:DB:1 [DB:laufendeUebung:ip(Username, Startzeit)] - Firewall schliessen (filtern nach Uebungsende anschalten) * Firewall-Daten der jeweiligen Uebung aus der Datenbank auslesen(?) I:KE:DB:2 (-> I:KE:DB_1) [DB:laufendeUebung:ip(Username, Startzeit)] * Firewall-Regeln entsprechend entfernen I:KE:FW:2 * Ggf. Sanity Check: wenn keine Uebungs mehr laeuft sollten nun keine FW-Regeln mehr aktiv sein - Aufgabentext praesentieren * URL/Pfad aus DB auslesen, abhaengig von d. gebuchten Uebung I:KE:DB:3 [DB:uebung:text(uebung_id)] * Uebungstext anzeigen - Ggf. Weiterfuehrende Informationen bereitstellen * Entweder in Kurs-DB oder im Aufgabentext verlinkt I:KE:DB:4 [DB:uebung:mehr_info(uebung_id)] - Uebungsende ueberwachen (per User oder Timeout) * HTML-Formular mit + Refresh Meta-Tag (Redirect auf "Fertig"-Seite; Problem: Schutz gegen Timer-Restart durch Reload?) und Refresh := DB:buchungen:startzeit + DB:uebung:dauer - now() + "Fertig"-Button anbieten (auf Aufgabentext-Seite?) * Verweis auf freiwilliges Ende oder Timeout mit entsprechendem Text quittieren * Benoetigte Uebungszeit hinterlegen (Statistik!): Script "uebung_ende" I:KE:DB:5 [DB:buchungen:endzeit(user_id, uebung_id, startzeit) = now()] * Auswertung starten: Script "uebung_ende" - Auswertung (via "uebung_ende") * Uebung als "wird ausgewertet" markieren [DB:buchungen:freigegeben(user_id,uebung_id,startzeit):= auswertung-laeuft] * Pfade der Check-Scripten & Rechner fuer Check-Scripten aus DB auslesen I:KE:DB:6 [DB:uebung_checks:*] * Interpreter aus 1. Zeile des Check-Scripts ermitteln * Absetzen der Check-Scripten: ssh $rechner $interpreter <$check_script (Optimierung wenn rechner == localhost, f. Tests "von aussen", z.B. vom Supervisor-Rechner aus, ob Dienst laeuft) * Rueckgabewert (OK/nicht OK) in Datenbank eintragen I:KE:DB:7 [DB:ergebnis_checks(Username,uebung_id,Startzeit,Script, Rechner) := ok/nicht ok] * Uebung als "niehr mehr freigegeben" markieren [DB:buchungen:freigegeben(user_id,uebung_id,startzeit):= nicht-mehr] - Zurueck zur Übersicht im User Management I:KE:UM:1 2.4 Scheduler Aktive Komponente, mit at(1) als Backend; User Management stoesst Jobs an (Uebung vorbereiten, nicht bestaetigte Anmeldungen loeschen, ...); Aufgaben: - Deployment starten * Eintrag "setup" at(1) Job durch User-Management beim Buchen der Kurse (-> I:UM:SC:1) I:SC:DE:1 - Loeschen unbestaetigter Anmeldungen * Per cron jede Nacht (Stunde, ...) gucken welche Accounts nicht bestaetigt sind, und loeschen (-> I:UM:DB:1) I:SC:DB:1, I:SC:SC_1 [DB:benutzer:freischalt_secret, DB:benutzer:anmeldedatum] - Loeschen von Firewall_Regeln fuer (abgebrochene/nicht angetretene?) übungen mit Script "uebung_ende" (-> I:DE:SC:1) I:SC:FW:1 2.5 Datenbank Speichert Daten ueber Benutzer, Uebungen, gebuchte Uebungen; Vorbereitete Übungen werden als solches gekennzeichnet (fuer naechstes Login des users: "Sie koennen jetzt ueben") Aufgaben: - Daten speichern (naja) (-> I:*:DB:*) Siehe Datenbank-Struktur unten fuer weitere Erklaerungen 2.6 Firewall Wird beim Login freigeschaltet, damit nur 1 User (Rechner? Subnetz?) Zugang zu den Uebungsrechnern hat. Implementierung über IPfilter / Port redirection. Daten werden von der Kursengine beim Start des Kurses abgefragt und scharf geschaltet. Nach Kurs-Ende werden die Daten wieder entfernt. Aufgaben: - Freizuschaltende IP-Nummer/Netzbits uebernehmen (-> I:KE:FW:1) - Firewall aufmachen, Interaktion mit IP Filter * Port-Redirection f. Uebungsrechner X, Ports 2[123] (incoming) => 2X02[123] - IPFilter: RDR ... * Admin Issues: - Wie Rules dynamisch in IPFilter laden? - Port-Freischaltung am RZ/FH-Firewall - Firewall zumachen, Interaktion mit IP Filter (-> I:KE:FW:2, I:SC:FW:1) 2.7 Deployment Scheduler stoesst Deployment an; Rechner werden automatisch ("ssh machine reboot"? kein Plan... :/) gebootet, per Default Netboot mit Bootloader fuer wahlweise Netboot (-> Deployment/Image restore) oder boot from local disk (-> Uebung). Nach erfolgreichem Deployment hinterlegen der Information ("Uebung aufgesetzt") in Datenbank - von Kursengine/User Management ausgewertet. Aufgaben: - Script "deploy DB:uebung:uebung_id" (-> I:SC:DE:1, vgl. I:UM:SC:1) - Uebung als "in Vorbereitung" markieren [DB:buchungen:freigegeben(user_id,uebung_id,startzeit):= deployment-in-progress] - Daten aus DB auslesen: welches Image auf welchen Rechner (fuer den jeweiligen Kurs) I:DE:DB:1 (XXX Scheduling welches Image auf welche Maschine fuer welche Aufgabe? Ggf. noch eigene Vermittlungsschicht dafuer, vorerst aber ausklammern) "deploy1 DB:uebung_setup:rechner DB:uebung_setup:image" (Mehr Details zum Deployment siehe "deployment" Text) [DB:uebung_setup:uebung_id==DB:uebung:uebung_id, DB:uebung_setup:rechner, DB:uebung_setup:image] - Eintrag "Deployment fertig" in DB hinterlegen I:DE:DB:2 [DB:buchungen:freigegeben(user_id,uebung_id,startzeit)=ja] - at-Job "uebung_ende" zum entfernen der Regeln bei abgebrochenen Übungen I:DE:SC:1 - Ggf. User via Mail benachrichtigen 3. Datenbank-Struktur: Tabelle "benutzer": *user_id serial login char(80) vorname char(50) nachname char(50) matrikel_nr char(50) email char(80) passwort char(15) freischalt_secret / "bestaetigt" char(80) anmeldedatum datum_t typ (admin, lehrer, prof) char(80) Tabelle "uebungen": *uebung_id char(40) bezeichnung char(150) nur_fuer char(40) vorlauf time dauer time nachlauf time wiederholbar? bool text (URL) char(150) mehr_info (URL) char(150) Tabelle "uebung_checks": *check_id serial uebung_id like DB:uebung:uebung_id script (Pfad?) char(150) parameter char(300) rechner (localhost, vulab1, ...) like DB:uebung_setup:rechner bezeichnung (f. Auswertung) char(150) Tabelle "buchungen": *buchungs_id serial *user_id like DB:benutzer:user_id *uebung_id like DB:uebung:uebung_id *startzeit time datum date (startdatum) freigegeben? nein/deployment-in-progress/ja/auswertung-laeuft/nicht-mehr endzeit time ip ("a.b.c.d/x") char(20) at_id int (deployment job) at_id_end int (end-of-uebung job) Tabelle "ergebnis_checks": *buchungs_id like DB:buchungen:buchungs_id *check_id like DB:uebung_checks:check_id erfolg bool Tabelle "uebung_setup": *uebung_id like DB:uebung:uebung_id *rechner like DB:uebungs_checks:rechner *image char(150) 4. Schnittstellendefinition: 4.1 User http, ssh, ftp 4.2 User Management Ruft auf (via): * Kursengine: CGI * Scheduler: at(1), cron(8) * Datenbank: PHP/pgsql Wird aufgerufen von (via): * Kursengine: - I:KE:UM:1: Rueckkehr nach Uebung (PHP/HTML) 4.3 Kursengine Ruft auf (via): * Datenbank: PHP/pgsql * Firewall: CGI Wird aufgerufen von (via): * User-Management: - I:UM:KE:1: Uebungsbeginn (PHP/HTML) 4.4 Scheduler Ruft auf (via): * Datenbank: sh/perl/PHP/pgsql * Deployment: sh/perl Wird aufgerufen von (via): * User-Management: - I:UM:SC:1: Übung buchen (at(1)) * Scheduler: - I:SC:SC:1: Periodischer Account-Purge 4.5 Datenbank Ruft auf (via): (nichts, keine aktive oder aktivierte Komponente, rein passiver Datenspeicher) Wird aufgerufen von (via): * User-Management: - I:UM:DB:1: User neu anmelden (PHP/pgsql) - I:UM:DB:2: Anmeldung bestätigen (2x) (PHP/pgsql) - I:UM:DB:3: Auslesen verfügbarer Kurse+Übungszeiten (PHP/pgsql) - I:UM:DB:4: Übung buchen (PHP/pgsql) - I:UM:DB:5: Abfrage ob Übung gebucht (PHP/pgsql) - I:UM:DB:6: Auswertung der von Checks eingegebenen Daten (PHP/pgsql) * Kursengine: - I:KE:DB:1: Firewall-Daten merken (PHP/pgsql) - I:KE:DB:2: Firewall-Daten loeschen (PHP/pgsql) - I:KE:DB:3: Übungstext anzeigen (PHP/pgsql) - I:KE:DB:4: Hintergrund-Infos anzeigen (PHP/pgsql) - I:KE:DB:5: Übungsdauer speichern (PHP/pgsql) - I:KE:DB:6: Daten zu Checks auslesen (perl/CGI/sh) - I:KE:DB:7: Check-Ergebnisse speichern (sh/perl) * Scheduler: - I:SC:DB:1: Unbestätigte Accounts löschen (sh/perl) * Deployment: - I:DE:DB:1: Infos ueber vorzubereitendes Deployment (sh) - I:DE:DB:2: Deployment fertig, Übung kann beginnen (sh) 4.6 Firewall Ruft auf (via): * Datenbank: perl/PHP/sh/pgsql Wird aufgerufen von (via): * Kursengine: - I:KE:FW:1: Öffnen vor Übung (CGI/perl/sh) - I:KE:FW:2: Schließen nach Übung (sh/perl) 4.7 Deployment Ruft auf (via): * Datenbank: perl/sh/pgsql Wird aufgerufen von (via): * Scheduler: - I:SC:DE:1: Übung vorbereiten (sh) 5. Übungen - Komponenten & Definition Aufbau und Erstellung von Übungen ist im Dokument "uebungserstellung.txt" beschrieben. 6. Diverses 6.1 Erweitern des Design mit Tutorieller Komponente fuer Benutzer (TK_B) User | | v| User Management | / | \ u| / | \ | / | \ l| Kurs Engine --- Datenbank ---- Scheduler | | \ / | \ | a| | /\ | \ | | | / Tutorielle \ | b| Firewall Komponente Deployment 1. User 2. User Management (UM) 3. Kursengine (KE) 4. Scheduler (SC) 5. Datenbank (DB) 6. Firewall (FW) 7. Deployment (DE) 8. Tutorielle Komponente fuer Benutzer (TK_B) 6.2 Admin-Uebung zum Image-Erzeugen/Editieren Idee: Definieren einer Uebung, deren Check-Scripten ein oder mehrere Images neu erzeugen. Anforderungen: - Darf nicht von Normaluser gebucht werden (kann Admin Ubung buchen?) - Zu aenderndes Image wird fuer die Uebung vorselektiert - Benennung des neuen Image-Dateinamens via Parameter - Check sorgen fuer Image-Erzeugung: admin-check-makeimage RECHNER=xx IMGNAME=$neuesimage - Beachtung genuegend grosser Nachlaufzeit! Checks: admin-check-clearharddisk admin-check-makeimage 6.3 Umorganisieren für bessere Datenstrukturen Die urspruenglich Entworfene Struktur mit Speichern der Übung in der Datenbank (Tabellen DB:uebungs_checks, DB:ergebnis_checks) hat das Problem, dass die Überprüfung relativ weit von der Aufgabenstellung entfernt ist. Alternative Varianten: 1. Übungstext -----> DB (check_nr) -----> Check-Script 2. Übungstext --------------------------> Check-Script 3. Übungstext zu 1.: Stand SS04 (7. Febl. 2004). Grund für Design: ursprünglich war keine (enge) Vermischung zwischen Aufgabentext und Überprüfung geplant: Übungstext | DB->Scripts(-ergebnis) (Anzeige waehrend | (Anzeige nach Übung) | Übung) Die Vermischung (2.) geschah, um bei der Auswertung (Anzeige der Übung) klarer zu machen, welche TeilÜbungen genau geprüft wird, und mit welchem Erfolg. Nachteil ist, dass Uebungstext und DB getrennt gewartet werden muessen. Abhilfe: Script 'uebung2db' liest Kommentare aus Uebungstext, und fuegt sie in die DB ein, so daß die manuelle Pflege entfällt, ohne die DB-Struktur ändern zu muessen. So koennen die Ergebnis-Checks an der selben Stelle wie der Aufgabentext gespeichert werden, zusaetzlich aber darueberhinaus mit Hilfe des DB-Frontends manipuliert werden, falls Bedarf besteht. zu 2.: Script-Aufruf, Parameter, Rechner & Bezeichnung f. Auswertung direkt bei Aufgabenstellung speichern Aufwand zur Realisierung: * Tabbel DB:uebungs_checks (+Erstell-Masken) loeschen * Tabelle DB:ergebnis_checks erhaelt als Ersatz für die Spalte check_id entweder das Tupel (rechner, script, parameter), oder die Bezeichnung (sollte innerhalb der Übung einmalig sein) oder eine Aufgabenweite laufende Nummer. * 3. Seite (3/3) bei Übungserstellung entfällt zu 3.: Check-Code direkt in Aufgabentext eingebettet Benötigt ID zum Mapping der Teilübungen -> Ergebnis in DB:ergebnis_checks (vgl. 3er-Tupel oder Bezeichnung etc. oben) Vorteil dieses Ansatzes: Einfachere Initialisierung der Datenstrukturen (In-Place, nicht in DB), vgl. [Spinellis:2001, "4.7. Data stucture representation", S. 96] 6.4 Komponenten-Graph generieren Der unter #1 aufgelistete Graph mit den Komponenten untereinander kann mit den Angaben aus Kapitel 4 (Schnittstellendefinition) automatisch erzeugt werden: ( echo "digraph vulab {" grep '.- I:..:..' design echo "}" ) | sed 's/.*I:\(..\):\(..\):.*/\1 -> \2/' > design_interactions.dot dot -Tgif design_interactions.dot >design_interactions0.gif Wenn man in der erzeugten Datei design_interactions.dot die erste Zeile als letztes nimmt und so einfach den Graph etwas umstrukturiert erhält man einen Graph der dem in Kapitel 1 schon recht nahe kommt, siehe design_interactions0.gif. -- $Id: design,v 1.48 2012-12-21 23:32:17 feyrer Exp $