class WatchIpGui: def __init__(self, master, title='IP Watchdog'): self.master = master self.master.title(title) self.menubar = Menu(self.master) self.cbInternalIp = BooleanVar() self.cbExternalIp = BooleanVar() self.cbHostname = BooleanVar() self.unitSelection = StringVar() self.watch = WatchIP() self.watch.getCurrentIP() self.vInternalIp = StringVar() self.vExternalIp = StringVar() self.vHostname = StringVar() self.isStarted = False self.newWindow = True self.preExec = False self.scale = None self.stop = True self.execWatchThread = None self.display() self.emailConfig = EmailConfigGui(master, False, properties='.ipwatcher.email.properties') def display(self, startExecution=False): self.startExecution = startExecution if self.newWindow == False: self.top.update() self.top.deiconify() if self.startExecution == True: self.action() else: curRow = 0 ## Menu Bar filemenu = Menu(self.menubar, tearoff=0) filemenu.add_command(label="Execute", command=self.action) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.quit) self.menubar.add_cascade(label="File", menu=filemenu) editmenu = Menu(self.menubar, tearoff=0) editmenu.add_separator() editmenu.add_command(label="Preferences", command=self.showPrefs) self.menubar.add_cascade(label="Edit", menu=editmenu) helpmenu = Menu(self.menubar, tearoff=0) helpmenu.add_command(label="IP Watchdog Help", command=self.helpButton) helpmenu.add_command(label="About...", command=self.showVersion) self.menubar.add_cascade(label="Help", menu=helpmenu) self.master.config(menu=self.menubar) ## End Menu Bar self.top = Toplevel(menu=self.menubar, width=500, relief=RAISED, borderwidth=2) self.top.protocol("WM_DELETE_WINDOW",self.quit) gridWidth = 30 px = 5 lWidth = 15 py = 18 #Grid Start #Notify on Change Label(self.top, text='Notify on Change in:', relief=RIDGE, bg='gray', width=gridWidth).grid(row=curRow, column=0, columnspan=2, pady=py) curRow += 1 Label(self.top, text='Internal IP', relief=RIDGE, width=15).grid(row=curRow, column=0) Checkbutton(self.top,variable=self.cbInternalIp).grid(row=curRow, column=1, sticky=W, padx=px) curRow += 1 Label(self.top, text='External IP', relief=RIDGE, width=15).grid(row=curRow, column=0) Checkbutton(self.top,variable=self.cbExternalIp).grid(row=curRow, column=1, sticky=W,padx=px) curRow += 1 Label(self.top, text='Hostname', relief=RIDGE, width=15).grid(row=curRow, column=0) Checkbutton(self.top,variable=self.cbHostname).grid(row=curRow, column=1, sticky=W,padx=px) #Change Frequency curRow += 1 Label(self.top, text='Poll Frequency:', relief=RIDGE, bg='gray', width=gridWidth).grid(row=curRow, column=0, columnspan=2, pady=py) curRow += 1 Label(self.top, text='Units', relief=RIDGE, width=15).grid(row=curRow, column=0) self.optionList = ['minute(s)','hour(s)','day(s)'] self.unitSelection.set(self.optionList[0]) OptionMenu(self.top, self.unitSelection, *self.optionList, command=self.updateInterval).grid(row=curRow, column=1, stick=EW) self.min = 5.0 self.max = 60.0 curRow += 1 Label(self.top, text='Interval', relief=SUNKEN, width=lWidth).grid(row=curRow, column=0,padx=px) self.scl = Scale(self.top, from_=self.min, to=self.max, orient=HORIZONTAL) self.scl.grid(row=curRow, column=1,padx=px) #Current Values curRow += 1 Label(self.top, text='Current Values:', relief=RIDGE, bg='gray', width=gridWidth).grid(row=curRow, column=0, columnspan=2, pady=py) curRow += 1 Label(self.top, text='Internal IP', relief=SUNKEN, width=lWidth).grid(row=curRow, column=0,padx=px) self.eInternalIp = Entry(self.top,state='readonly', textvariable=self.vInternalIp) self.eInternalIp.grid(row=curRow, column=1, sticky=W,padx=px) curRow += 1 Label(self.top, text='External IP', relief=SUNKEN, width=lWidth).grid(row=curRow, column=0,padx=px) self.eExternalIp = Entry(self.top,state='readonly', textvariable=self.vExternalIp) self.eExternalIp.grid(row=curRow, column=1, sticky=W,padx=px) #self.vExternalIp.set() curRow += 1 Label(self.top, text='Hostname', relief=SUNKEN, width=lWidth).grid(row=curRow, column=0, padx=px) self.eHostname = Entry(self.top,state='readonly', textvariable=self.vHostname) self.eHostname.grid(row=curRow, column=1, sticky=W,padx=px) #Actions curRow += 1 Label(self.top, text='Actions:', relief=RIDGE, bg='gray', width=gridWidth).grid(row=curRow, column=0, columnspan=2, pady=py) curRow += 1 Button(self.top, text='Quit',bg='blue', fg='white', command=self.quit).grid(row=curRow,column=0, pady=5) self.actionButton =Button(self.top, text='Start',bg='blue', fg='white', command=self.action) self.actionButton.grid(row=curRow,column=1, pady=5) self.updateEntries() self.newWindow = False #Grid End def updateEntries(self): self.vInternalIp.set(self.watch.curInternalIp) self.vExternalIp.set(self.watch.curExternalIp) self.vHostname.set(self.watch.curHostName) def showPrefs(self): self.emailConfig.display(self, self.preExec) self.top.withdraw() def helpButton(self): pass def showVersion(self): pass def quit(self): if self.execWatchThread != None: if self.execWatchThread.isAlive(): self.execWatchThread.join() os.sys.exit(0) def action(self): if not self.isStarted: if self.emailConfig.checkMissingConfig() == True: self.preExec = True msg = "Please configure the outgoing email." tkMessageBox.showinfo('Configure Email', msg) self.showPrefs() elif self.emailConfig.getPassword() == "": self.preExec = True msg = "Enter your password to start watching." tkMessageBox.showinfo('Authenticate', msg) self.showPrefs() else: self.getNotificationList() if len(self.notifyList) == 0: tkMessageBox.showerror("Insufficient Input", "Please check an item to watch.") else: msg = "I will minimize the window and then I will poll the system in " + str(self.scl.get()) + " " + self.unitSelection.get().replace('(s)','') msg += " intervals. Finally I will email/text on change in:\n\n" + '\n'.join(self.notifyList) if tkMessageBox.askokcancel('Execute Confirmation', msg): self.isStarted = not self.isStarted self.actionButton.config(text='Stop') self.top.iconify() self.normalizeInterval() em = self.emailConfig self.execWatchThread = ExecuteWatchThread(self.scale, em.fromAddress.get(),em.getPassword(),em.recipients.get(), self.cbInternalIp.get(), self.cbExternalIp.get(), self.cbHostname.get(), em.server.get(), em.port.get()) self.execWatchThread.start() # self.emailOnChange() # self.top.deiconify() print "Done" else: self.actionButton.config(text='Start') self.isStarted = not self.isStarted if self.execWatchThread.isAlive(): self.execWatchThread.join() print "She is gone" print "Living? ", self.execWatchThread.isAlive() def getNotificationList(self): self.notifyList = [] if self.cbExternalIp.get(): self.notifyList.append('External IP') if self.cbInternalIp.get(): self.notifyList.append('Internal IP') if self.cbHostname.get(): self.notifyList.append('Hostname') def emailOnChange(self): self.normalizeInterval() print "Is Started: ", self.isStarted if self.scale != None: while self.isStarted == True: time.sleep(30) if self.watchedValueHasChange() == True: tkMessageBox.showinfo("Change Detected", self.watch.getCurrentIpString()) else: tkMessageBox.showinfo("No Change Detected", self.watch.getCurrentIpString()) print "Is Started: ", self.isStarted def normalizeInterval(self): self.scale = self.scl.get() if self.unitSelection.get() == 'minutes(s)': self.scale = self.scale * 60 elif self.unitSelection.get() == 'hour(s)': self.scale = self.scale * 60 * 60 elif self.unitSelection.get() == 'days(s)': self.scale = self.scale * 24 * 60 * 60 else: self.ErrStr = "Error: Unknown unit --> " + str(self.unitSelection.get()) print self.scale self.scale = 120 def updateInterval(self, event=None): if self.unitSelection.get() == self.optionList[0]: self.min = 5 self.max = 60 elif self.unitSelection.get() == self.optionList[1]: self.min = 1 self.max = 24 else: self.min = 1 self.max = 7 self.scl.config(from_=self.min) self.scl.config(to=self.max)
class SimpleNotificationSystem(): def __init__(self,master,title='Simple Notification System (SNS)'): self.pathToExe =StringVar() self.args = StringVar() self.master = master self.menubar = Menu(self.master) self.title = title self.newWindow = True self.preExec = False self.logDir = ""#'..' + os.sep + 'logs' self.spacer = '*' * 80 + '\n' self.spacer += self.spacer + '\n' dateStamp = str(datetime.date.today()) + strftime("_%H%M%S") self.errorLog = self.logDir + os.sep + 'SNS.' + str(dateStamp) + ".log" writeLog(self.errorLog, "Starting SNS on .... " + str(dateStamp) + "\n") writeLog(self.errorLog, self.spacer) self.emailConfig = EmailConfigGui(master, False, self.errorLog) if self.emailConfig.checkMissingConfig() == True: message = "This is either the first time you have run this program " message += "or you are missing some required configuration" tkMessageBox.showinfo('Required Configuration Options', message) self.emailConfig.display(self) else: self.display() def cancel(self): #tkMessageBox.showinfo("Cheers", "Have a good one :) " ) os.sys.exit(0) def helpButton(self): pass def showVersion(self): pass def submit(self): text = 'COMMAND RESULTS:\n' self.preExec = True if self.emailConfig.checkMissingConfig() == True: msg = "Please configure the outgoing email." tkMessageBox.showinfo('Configure Email', msg) self.showPrefs() elif self.emailConfig.getPassword() == "": msg = "Enter your password, hit apply and then resubmit" tkMessageBox.showinfo('Authenticate', msg) self.showPrefs() else: msg = 'Shall I minimize the window and execute ' + os.path.basename(self.pathToExe.get()) + ' now?' if tkMessageBox.askokcancel('Execute Confirmation', msg): self.top.iconify() try: text += self.captureOutput(self.pathToExe.get() + " " + self.args.get()) subject = self.pathToExe.get() + " <-- Command completed" emObj = self.emailConfig email = EmailWrapper(emObj.recipients.get(),subject,text, emObj.fromAddress.get(), emObj.getPassword(),emObj.server.get(),emObj.port.get()) email.mail() if email.hasErrors == True: msg = email.errString msg += "\nValues: \n" msg += email.toString() tkMessageBox.showerror('Mail Error Generated', msg) self.top.deiconify() else: tkMessageBox.showinfo("Execution Complete", subject) self.top.deiconify() except IOError as inst: output = "ERROR GENERATED in EmailAfterExec.submit:\n" output += "Exception Type: " + str(type(inst)) + "\n" output += "Exception: " + str(inst) + "\n" tkMessageBox.showerror('Submit Error Generated', output) self.top.deiconify() ## ---------------------------------------------------------------------------- ## captureOutput - Wrapper function that captures the standard output of an ## external command and returns that ouput in string format ## ## ---------------------------------------------------------------------------- def captureOutput(self, cmd): try: stream = os.popen(cmd) output = stream.read() stream.close() except Exception as inst: output = "ERROR GENERATED:\n" output += "CMD: " + cmd + "\n" output += "Exception Type: " + str(type(inst)) + "\n" output += "Exception: " + str(inst) + "\n" return str(output) def showPrefs(self): self.emailConfig.display(self,self.preExec) self.top.withdraw() def browseForExe(self): tmp = askopenfilename() if tmp != "": self.pathToExe.set(tmp) def display(self, startExecution=False): self.startExecution = startExecution if self.newWindow == False: self.top.update() self.top.deiconify() if self.startExecution == True: self.submit() else: ## Menu Bar filemenu = Menu(self.menubar, tearoff=0) filemenu.add_command(label="Execute", command=self.submit) filemenu.add_separator() filemenu.add_command(label="Exit", command=self.cancel) self.menubar.add_cascade(label="File", menu=filemenu) editmenu = Menu(self.menubar, tearoff=0) editmenu.add_separator() editmenu.add_command(label="Preferences", command=self.showPrefs) self.menubar.add_cascade(label="Edit", menu=editmenu) helpmenu = Menu(self.menubar, tearoff=0) helpmenu.add_command(label="Email After Execution Help", command=self.helpButton) helpmenu.add_command(label="About...", command=self.showVersion) self.menubar.add_cascade(label="Help", menu=helpmenu) self.master.config(menu=self.menubar) ## End Menu Bar #self.top = Toplevel(self.master) self.top = Toplevel(menu=self.menubar, width=500, relief=RAISED, borderwidth=2) self.top.protocol("WM_DELETE_WINDOW",self.cancel) self.top.title(self.title) self.top.resizable(width=FALSE, height=FALSE) Label(self.top, text="Programs To Execute", bd=2,relief=SOLID,width=60, bg='gray').grid(columnspan=2,row=6, pady=8) Label(self.top, text="Path", bd=2,relief=SOLID,width=30).grid(row=7,sticky=W) self.ePath = Entry(self.top,width=35, textvariable=self.pathToExe) self.ePath.grid(row=7,column=1, pady=3, padx=5,sticky=W) Button(self.top, text='+',bg='blue', fg='white', command=self.browseForExe).grid(row=7,column=2) Label(self.top, text="Args", bd=2,relief=SOLID,width=30).grid(row=8,sticky=W) self.eArgs = Entry(self.top,width=35, textvariable=self.args) self.eArgs.grid(row=8,column=1, pady=3, padx=5,sticky=W) Button(self.top, text='Help',bg='gray', fg='white', command=self.cancel).grid(row=9,column=0,pady=10) Button(self.top, text='Submit',bg='blue', fg='white', command=self.submit).grid(row=9,column=1,pady=10) Button(self.top, text='Quit',bg='red', fg='white', command=self.cancel).grid(row=9,column=2,pady=10) self.newWindow = False