E.3.1 Hauptprogramm des Monitor-/Steuerungswerkzeug

#!/usr/local/bin/python
# -------------------------------------------------------------
# Projekt : Digitale Bibliotheken Projekt
# Uni-Frankfurt/M, Professur Telematik und
# verteilte Systeme, Prof. O. Drobnik
# Diplomarbeit, Matzen,Hans, 1997
#
# Dateiname : monitor.py
# Datum : 03.11.1997
# letzte Änderung : 08.01.1998
# Autor : Hans Matzen, 1997, Frankfurt/M, Deutschland
# Sprache : Python v1.4
# Beschreibung : Managementobjekt mit kombinierter
# Monitor-/Steuerungsfunktionalität
# Anmerkungen :
#
# -------------------------------------------------------------
 
 
# imports fuer Tk, Socketkommunikation und Stringverarbeitung
from Tkinter import *
import socket
import string
 
 
#
# Klasse des Monitor-/Steuerungswerkzeuges
#
class moni:
    #
    # Konstruktor
    #
    def __init__(self,master):
        # Variablen setzen und Socket erzeugen
        self.master=master
        self.br_anz=0
        self.sp_anz=0
        self.if_anz=0
        self.upint=5
        self.widgets={}
        self.host="localhost"
        self.port=6444
        self.connected=0
        self.conn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.confstr=""
 
        # GUI aufbauen
        self.create_everything()
 
 
    #
    # Zeichnet die Oberflaeche und ordnet
    # die Ereignisse zu
    #
    def create_everything(self):
        #
        # Menues
        #
        self.mbar=Frame(self.master,relief=RAISED, bd=2)
        self.mbar.pack(side=TOP, fill=X)
        # menuebuttons einrichten
        self.m_verbindung =Menubutton(self.mbar,text="Verbindung",underline=0)
        self.m_broker =Menubutton(self.mbar,text="Broker",underline=0)
        self.m_options =Menubutton(self.mbar,text='Options',underline=0)
        self.m_info =Menubutton(self.mbar,text="Info",underline=0)
 
        self.m_verbindung.pack(side=LEFT)
        self.m_broker.pack(side=LEFT)
        self.m_options.pack(side=LEFT)
        self.m_info.pack(side=RIGHT)
        # menueeintraege erzeugen
        self.m1=Menu(self.m_verbindung,tearoff=NO)
        self.m1.add_command(label="Aufbauen",underline=0,command=self.br_connect)
        self.m1.add_command(label="Abbauen",underline=0,command=self.br_disconnect)
        self.m1.add_command(label="Beenden",underline=0,command=self.ende)
 
        self.m2=Menu(self.m_broker,tearoff=NO)
        self.m2.add_command(label="Anhalten",underline=0,command=self.br_stop)
        self.m2.add_command(label="Fortsetzen",underline=0,command=self.br_cont)
        self.m2.add_command(label="Manuelle Verteilung",underline=0,command=self.br_man)
        self.m2.add_command(label="Automatische Verteilung",underline=0,command=self.br_auto)
 
 
        self.m3=Menu(self.m_info,tearoff=NO)
        self.m3.add_command(label="Info",underline=0,command=self.info1)
 
        self.m4=Menu(self.m_options,tearoff=NO)
        self.m4.add_command(label="Update",underline=0,command=self.brupdate)
        self.m4.add_command(label="Parameter",underline=0,command=self.br_parms)
        # menubuttons mit menues verbinden
        self.m_verbindung.config(menu=self.m1)
        self.m_broker.config(menu=self.m2)
        self.m_options.config(menu=self.m4)
        self.m_info.config(menu=self.m3)
        # frame mit menubuttons als menueleiste einrichten
        self.mbar.tk_menuBar(self.m_verbindung, self.m_broker, self.m_options,self.m_info)
 
        # diagramm bereich einrichten
        self.f2=Frame(self.master)
        self.f2.pack()
        self.draw=Canvas(self.f2, bg='Black', height=400, width=500,scrollregion=(0,0,1000,400))
        self.draw.pack()
        self.dsbx=Scrollbar(self.f2,orient=HORIZONTAL)
        self.dsbx.pack(fill=X,side=BOTTOM,expand=YES)
        self.draw.config(xscrollcommand=self.dsbx.set)
        self.dsbx.config(command=self.draw.xview)
         
        self.draw.bind("<Double-Button-1>",self.action)
 
        # updateintervall selektor montieren
        self.f4=Frame(self.master)
        self.f4.pack(fill=X)
 
        self.f3=Frame(self.f4,relief=SUNKEN,bd=3)
        self.f3.pack(side=LEFT,fill=X)
        self.sc1=Scale(self.f3,{'from':0,'to':300}, label="Updateintervall (sek.)",showvalue=YES,orient=HORIZONTAL,length=300,tickinterval=50,command=self.setupint)
        self.sc1.pack(side=LEFT)
        self.sc1.set(self.upint)
 
        # Status Ampel
        from ampel import ampel
        self.f5=Frame(self.f4,relief=SUNKEN,bd=3)
        self.f5.pack(side=RIGHT)
        self.amp=ampel(self.f5,20)
        self.amp.pack("side=RIGHT")
        self.amp.switch(3)
        self.amp.bind("<1>",self.connchange)
        self.lamp=Label(self.f5,text="Nicht verbunden")
        self.lamp.pack(side=LEFT)
         
        # buttons anbringen
        self.f1=Frame(self.master)
        self.f1.pack(side=RIGHT,fill=X)
        self.b4= Button(self.f1, text='Quit', command=self.ende)
        self.b4.pack(side=RIGHT)
         
# --------------------------- Ereignismethoden -------------------
 
    #
    # Beendet das M/S Werkzeug
    #
    def ende(self):
        # wenn wir noch mit dem Broker verbunden sind
        if self.connected==1:
            # beim Broker abmelden
            self.br_disconnect()
        raise SystemExit
 
    #
    # Wertet einen Mausklicks auf die Ampel aus
    # und ruft die entsprechenden Methoden auf
    #
    def connchange(self,event):
        # ermitteln welches Ampellicht angeklickt wurde
        typ=self.amp.which(event.x,event.y)
        # gruen wurde geklickt, wenn wir noch nicht mit
        # dem Broker verbunden sind dann Verbindung aufbauen
        if typ==3:
            if self.connected==0:
                self.br_connect()
        # gelb wurde angeklickt, siehe oben
        elif typ==2:
            if self.connected==0:
                self.br_connect()
            self.brupdate()
        # rot wurde angeklickt, wenn wir mit dem Broker
        # verbunden sind dann trenne Verbindung
        else:
            if self.connected==1:
                self.br_disconnect()
 
    # setzt neues updateintervall, immer dann wenn
    # der schieberegler veraendert wurde
    def setupint(self,x):
        self.upint=self.sc1.get()
 
    #
    # ermittelt auf welche Instanz im Hauptfenster ein
    # Doppelklick ausgefuehrt wurde und zeigt das
    # entsprechende Konfigurationsfenster an.
    #
    def action(self,event):
        x=event.x
        y=event.y
        #ermittle objektname
        for i in self.widgets.keys():
            a=self.widgets[i]
            xo=a[8][0]
            yo=a[8][1]
            if (x >=xo) and (x<=xo+100) and (y>=yo) and (y<=yo+100):
                obj=i
        # suche objekt in configstring
        self.olist=[]
        clist=string.split(self.confstr,";")
        # ist es der Broker
        if string.split(clist[0][2:-2],",")[0]==obj:
            list=string.split(clist[0][2:-2],",")
            self.olist=["Broker",list[0],self.host,str(self.port),list[1],list[2],list[3]]
        else:
            spl=eval(clist[1])
            for j in spl.keys():
                if spl[j][1]==obj:
                    self.olist=["Speicher",spl[j][1],spl[j][2],spl[j][3],spl[j][4],"0","0"]
        if self.olist==[]:
             afl=eval(clist[2])
            for j in afl.keys():
                if afl[j][1]==obj:
                    self.olist=["Auftrag",afl[j][1],afl[j][2],afl[j][3],afl[j][4],"0","0"]
 
 
 
        # fenster mit der konfiguration des objekts anzeigen
        self.iw=Tk()
        if1=Frame(self.iw)
        if1.pack(fill=X)
        if2=Frame(self.iw)
        if2.pack(side=BOTTOM)
        ml1=Label(if1,text="Objekttyp : "+self.olist[0])
        ml2=Label(if1,text="Objektname : "+self.olist[1])
        ml3=Label(if1,text="Hostname : "+self.olist[2])
        ml4=Label(if1,text="Port : "+self.olist[3])
 
        self.objstate=self.olist[4]
        ml5=Frame(if1)
 
        self.vcb1=StringVar()
        rb1=Radiobutton(ml5,text="Laufend",value="r",variable=self.vcb1,command=self.sv_1)
        rb2=Radiobutton(ml5,text="Angehalten",value="s",variable=self.vcb1,command=self.sv_2)
        rb3=Radiobutton(ml5,text="Terminiert",value="t",variable=self.vcb1,command=self.sv_3)
        rb1.pack(side=LEFT)
        rb2.pack(side=LEFT)
        rb3.pack(side=LEFT)
        if self.objstate=="run":
            rb1.select()
            self.vcbt="run"
        elif self.objstate=="paused":
            rb2.select()
            self.vcbt="paused"
        else:
            rb3.select()
 
        ml6=Label(if1,text="Aufträge : "+self.olist[5])
        if self.olist[0]=="Broker":
            ml7=Label(if1,text="offene Auftr. : "+self.olist[6])
        elif self.olist[0]=="Speicher":
            ml7=Label(if1,text="Auslastung : "+self.olist[6])
        else:
           ml7=Label(if1,text="")
  
        bl1=Button(if2,text="OK",width=10,command=self.setobj_parms)
        bl2=Button(if2,text="Cancel",width=10,command=self.iw.destroy)
        ml1.pack(anchor="w")
        ml2.pack(anchor="w")
        ml3.pack(anchor="w")
        ml4.pack(anchor="w")
        ml5.pack(anchor="w")
        ml6.pack(anchor="w")
        ml7.pack(anchor="w")
        bl1.pack(side=LEFT)
        bl2.pack(side=LEFT)
        self.iw.wait_window(self.iw)
        del self.iw
 
         
    #
    # Drei Hilfsroutinen zum auslesen
    # der Parameter des Konfigurationsfensters
    #
    def sv_1(self):
        self.vcbt="run"
    def sv_2(self):
        self.vcbt="paused"
    def sv_3(self):
        self.vcbt="term"
 
    #
    # sendet eine Zustandsaenderung an den Broker
    #
    def setobj_parms(self):
        # commando erstellen
        self.vcb1=self.vcbt
        self.objstate= self.vcb1
        commandstr="CMD_CHGST "+self.olist[1]+" "+self.objstate
        # Kommando an Broker senden
        if self.connected==1:
            self.conn.send(commandstr)
        self.iw.destroy()
        del self.olist, self.objstate, self.vcb1, self.vcbt
 
    #
    # aktualisiert die graphische Anzeige
    #
    def refresh(self,confstr):
        # alte widgets löschen
        for i in self.widgets.keys():
            for j in range(0,8):
                w=self.widgets[i][j]
                self.draw.delete(w)
 
        self.widgets={}
        self.sp_anz=0
        self.br_anz=0
        self.if_anz=0
        self.master.update_idletasks()
        # neue widgets aufbauen
        clist=string.split(confstr,";")
        # Broker erzeugen
        brlist=string.split(clist[0][2:-2],",")
        brstr="X,"+brlist[0]+","+self.host+","+str(self.port)+","+brlist[1]+","+brlist[2]+","+brlist[3]
        self.broker(brstr)
        # Speicher erzeugen
        spdict=eval(clist[1])
        for i in spdict.keys():
            spl=spdict[i]
            spstr=str(spl[0])+","+spl[1]+","+spl[2]+","+spl[3]+","+spl[4]+",0,0"
            self.speicher(spstr)
 
        ifdict=eval(clist[2])
        for i in ifdict.keys():
            ifl=ifdict[i]
             
    #
    # Zeichnet eine Auftragsinstanz
    #
    def auftrag(self,confstr=""):
        # Koordinaten berechnen
        y=10
        x=self.if_anz*105+5
 
        if confstr!="":
            clist=string.split(confstr,",")
        else:
            clist=[" "," "," "," "," "," "," "]
        n=str(clist[1])
        h=str(clist[2])
        p=str(clist[3])
        s=str(clist[4])
        c=str(clist[5])
 
        # Auftrag zeichnen
        s0=self.draw.create_rectangle(x,y,x+100,y+100,fill='lightGreen')
        s1=self.draw.create_text(x+1,y+10,text="Name:"+n,anchor='w',width=95)
        s2=self.draw.create_text(x+1,y+25,text="Host:"+h,anchor='w',width=95)
        s3=self.draw.create_text(x+1,y+40,text="Port:"+p,anchor='w',width=95)
        s4=self.draw.create_text(x+1,y+55,text="State:"+s,anchor='w',width=95)
        s5=self.draw.create_text(x+1,y+70,text="Count:"+c,anchor='w',width=95)
        self.if_anz=self.if_anz+1
        s6=""
        s7=self.draw.create_line(x+50,y+100,self.br_anz*50+5,150,fill="yellow",width="5",arrow=BOTH)
        s8=(x,y)
        # Widgets merken damit man weiter darauf zugreifen kann
        self.widgets[n]=(s0,s1,s2,s3,s4,s5,s6,s7,s8)
         
    #
    # zeichnet eine Speicherinstanz
    #
    def speicher(self,confstr=""):
        # Koordinaten berechnen
        y=290
        x=self.sp_anz*105+5
 
        if confstr!="":
            clist=string.split(confstr,",")
        else:
            clist=[" "," "," "," "," "," "," "]
        n=str(clist[1])
        h=str(clist[2])
        p=str(clist[3])
        s=str(clist[4])
        c=str(clist[5])
        l=str(clist[6])
        # Speicher zeichnen
        s0=self.draw.create_rectangle(x,y,x+100,y+100,fill='moccasin')
        s1=self.draw.create_text(x+1,y+10,text="Name :"+n,anchor='w',width=90)
        s2=self.draw.create_text(x+1,y+25,text="Host :"+h,anchor='w',width=90)
        s3=self.draw.create_text(x+1,y+40,text="Port :"+p,anchor='w',width=90)
        s4=self.draw.create_text(x+1,y+55,text="State:"+s,anchor='w',width=90)
        s5=self.draw.create_text(x+1,y+70,text="Count:"+c,anchor='w',width=90)
        s6=self.draw.create_text(x+1,y+85,text="Load :"+l,anchor='w',width=90)
        self.sp_anz=self.sp_anz+1
        s7=self.draw.create_line(x+50,y,self.br_anz*50+5,250,fill="white",width="5",arrow=BOTH)
        s8=(x,y)
 
        # Widgets merken damit man weiter darauf zugreifen kann
        self.widgets[n]=(s0,s1,s2,s3,s4,s5,s6,s7,s8)
 
    #
    # zeichnet eine Brokerinstanz
    #
    def broker(self,confstr=""):
        # berechne Koordinaten
        y=150
        x=self.br_anz*105+5
 
        if confstr!="":
            clist=string.split(confstr,",")
        else:
            clist=[" "," "," "," "," "," "," "]
        n=str(clist[1])
        h=str(clist[2])
        p=str(clist[3])
        s=str(clist[4])
        c=str(clist[5])
        q=str(clist[6])
        # Zeichne Broker
        s0=self.draw.create_rectangle(x,y,x+100,y+100,fill='Red')
        s1=self.draw.create_text(x+1,y+10,text="Name : "+n,anchor='w')
        s2=self.draw.create_text(x+1,y+25,text="Host : "+h,anchor='w')
        s3=self.draw.create_text(x+1,y+40,text="Port : "+p,anchor='w')
        s4=self.draw.create_text(x+1,y+55,text="State : "+s,anchor='w')
        s5=self.draw.create_text(x+1,y+70,text="Count : "+c,anchor='w')
        s6=self.draw.create_text(x+1,y+85,text="Queued: "+q,anchor='w')
        self.br_anz=self.br_anz+1
        s7=""
        s8=(x,y)
        # Widgets merken damit man weiter darauf zugreifen kann
        self.widgets[n]=(s0,s1,s2,s3,s4,s5,s6,s7,s8)
         
    #
    # Zeigt das About an
    #
    def info1(self):
        iw=Tk()
        if1=Frame(iw)
        if1.pack()
        m1=Message(if1,text="Monitor V0.99\n\n (c) by Hans Matzen, 1997,\n
           Germany, Frankfurt/M\n email: hans@tm.informatik.uni-frankfurt.de"
,
           width="10c")
        b1=Button(if1,text="OK",command=iw.destroy)
        m1.pack()
        b1.pack()
        iw.wait_window(iw)
        del iw
 
    #
    # zeigt das Konfigurationsfenster fuer die Brokerparameter an
    #
    def br_parms(self):
        # fenster aufbauen
        self.iw=Tk()
        self.if1=Frame(self.iw)
        self.if1.pack()
        self.if2=Frame(self.iw)
        self.if2.pack(side=BOTTOM)
        self.ml1=Label(self.if1,text="Hostname:")
        self.ml2=Entry(self.if1,width=30)
        self.ml3=Label(self.if1,text="Port:")
        self.ml4=Entry(self.if1,width=30)
        self.bl1=Button(self.if2,text="OK",width=10,command=self.setbr_parms)
        self.bl2=Button(self.if2,text="Cancel",width=10,command=self.iw.destroy)
        self.ml1.pack()
        self.ml2.pack()
        self.ml3.pack()
        self.ml4.pack()
        self.bl1.pack(side=LEFT)
        self.bl2.pack(side=LEFT)
        self.ml2.insert(END,self.host)
        self.ml4.insert(END,str(self.port))
        # warten bis Fenster geschlossen wird
        self.iw.wait_window(self.iw)
         
 
    #
    # setzt die im konfigurationsfenster gesetzten werte
    #
    def setbr_parms(self):
        self.host=self.ml2.get()
        self.port=eval(self.ml4.get())
        self.iw.destroy()
        del self.iw
 
 
    #
    # baut die Verbindung zum Broker auf
    #
    def br_connect(self):
        # pruefe ob bereits verbunden
        if self.connected==0:
            # versuche verbindung aufzubauen
            try:
                # connect durchfuehren
                self.conn.connect(self.host,self.port)
                # anzeige aktualisieren
                self.lamp.config(text="Verbunden")
                self.amp.switch(1)
                self.connected=1
                # automatische aktualisierung der Statusdaten starten
                self.master.after(self.upint*1000,self.brupdate)
            except:
                # wenns nicht klappt
                # zeige Fehlermeldung
                import time
                self.lamp.config(text="Verbindungsfehler")
                self.amp.switch(2)
                self.master.update_idletasks()
                time.sleep(3)
                self.lamp.config(text="Nicht verbunden")
                self.amp.switch(3)
             
    #
    # fordert beim Broker die aktuellen Statusdaten an
    # und zeigt sie an
    #
    def brupdate(self):
        # sind wir verbunden ?
        if self.connected==1:
            # wenn ja fordere statusdaten beim broker an
            self.conn.send("CMD_CONFGET")
            # warte auf antwort vom Broker
            self.confstr=self.conn.recv(8192)
            # anzeigen aktualisieren
            self.refresh(self.confstr)
            self.amp.switch(1)
            self.master.update_idletasks()
            # automatischen update starten
            self.master.after(self.upint*1000,self.brupdate)
 
 
    #
    # trennt die Verbindung zum Broker
    #
    def br_disconnect(self):
        # sind wir verbunden ?
        if self.connected==1:
            # wenn ja sende Meldung an Broker
            self.conn.send("QUIT")
            self.conn.close()
            del self.conn
            # hole neuen Socket fuer naechste Verbindung
            self.conn=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            self.connected=0
            # aktualisiere Anzeige
            self.lamp.config(text="Nicht verbunden")
            self.amp.switch(3)
 
 
    #
    # hält den Broker an
    #
    def br_stop(self):
        if self.connectd==1:
            self.conn.send("CMD_PAUSE")
 
    #
    # startet den broker wieder
    #
    def br_cont(self):
        if self.connectd==1:
            self.conn.send("CMD_CONT")
 
    #
    # sendet einen Zuordnungsauftrag an den Broker
    #
    def br_mapcommand(self,job,spname):
        if self.connectd==1:
            self.conn.send("CMD_MAPJOB "+str(job)+" "+str(spname))
    #
    # schaltet auf manuelle verteilung um
    #
    def br_man(self):
        if self.connectd==1:
            self.conn.send("CMD_MAN")
     
    #
    # schaltet auf automatische verteilung um
    #
    def br_auto(self):
        if self.connectd==1:
            self.conn.send("CMD_AUTO")
 
 
#
# Hauptprogramm
#
root=Tk()
to=moni(root)
root.mainloop()