source: palm/trunk/SCRIPTS/palm_wd @ 1611

Last change on this file since 1611 was 1611, checked in by maronga, 9 years ago

added new palm watchdog, removed old nc2vdf scripts

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 29.3 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#--------------------------------------------------------------------------------#
4# This file is part of PALM.
5#
6# PALM is free software: you can redistribute it and/or modify it under the terms
7# of the GNU General Public License as published by the Free Software Foundation,
8# either version 3 of the License, or (at your option) any later version.
9#
10# PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# PALM. If not, see <http://www.gnu.org/licenses/>.
16#
17# Copyright 1997-2015  Leibniz Universitaet Hannover
18#--------------------------------------------------------------------------------#
19#
20# Current revisions:
21# -----------------
22# Initial revision
23#
24# Former revisions:
25# -----------------
26# $Id: palm_wd 1611 2015-07-07 12:23:22Z maronga $
27#
28#
29# Description:
30# ------------
31# PALM watchdog client for monitoring batch jobs on a variety of hosts specified
32# by the user
33#
34# Instructions:
35# -------------
36# 1) Modify the header section of palm_wd
37# 2) Move .wd.olddata and .wd.newdata to your palm directory
38#    (e.g. /home/user/current_version/.wd.newdata etc.)
39# 3) Modify a copy of palm_wdd for each host to be monitored and move it to the
40#    respective hosts
41# 4) Start the client either from mrungui or from shell by "nohup palm_wd&"
42
43# To do:
44# ------
45# 1) Add "Options", "Help" and "Manual"
46# 2) Move user settings to a configuration file
47#------------------------------------------------------------------------------!
48
49import sys
50import subprocess as sub
51from PyQt4 import QtGui, QtCore, uic
52from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
53import time
54import datetime
55import shutil
56import os
57
58# START OF HEADER
59# Each list must contain the login host, the username and a description
60hostname     = ["hlogin.hlrn.de", "blogin.hlrn.de"]
61username     = ["nikmaron"      , "nikmaron"      ]
62description  = ["Hannover"      , "Berlin"        ]
63
64update_frequency = 600*1000
65
66# END OF HEADER
67
68# Determine PALM directories
69try: 
70   devnull = open(os.devnull, 'w')
71   out = sub.check_output("echo $PALM_BIN", shell=True, stderr=sub.STDOUT)
72   palm_bin = out.rstrip()
73   palm_dir = out.split("palm")[0] + "palm/" + out.split("palm")[1].split("/")[1]
74   out = None
75except:   
76   print "Error. $PALM_BIN is not set."
77   raise SystemExit
78
79
80# Dummy variables for the jobname and the progressbars
81jobname = ""
82timestamp = ""
83pbars = []
84job_data_list = []
85
86# MainWindow class
87class Watchdog(QtGui.QMainWindow):
88   
89    def __init__(self):
90        super(Watchdog, self).__init__()
91       
92        self.InitUi()   
93       
94   
95    # Initialized MainWindow UI
96    def InitUi(self):
97
98        # Load predefined mainwindow
99        uic.loadUi(palm_bin + '/palm_wd_files/wd.ui', self)
100
101        # Resize columns and set number of rows to zero. Column 6 is hidden and
102        # contains the remote jobname (e.g. hannover.174610)
103        self.table.setColumnWidth(0,230)
104        self.table.setColumnWidth(1,80)
105        self.table.setColumnWidth(2,50)
106        self.table.setColumnWidth(3,80)     
107        self.table.setColumnWidth(4,180)
108        self.table.setColumnWidth(5,115)   
109        self.table.setColumnHidden(6, True)
110        self.table.setRowCount(0) 
111       
112        # Display MainWindow
113        self.show()
114        QtGui.QApplication.processEvents()
115
116        # Start refresh timer. On timeout perform update
117        self.timer = QtCore.QTimer(self)
118        self.timer.timeout.connect(self.Refresh)
119        self.timer.setSingleShot(False)
120        self.timer.start(update_frequency)
121
122        # The timetimer counts the time since last update
123        self.timetimer= QtCore.QElapsedTimer()
124        self.timetimer.start()
125
126        # The labeltimer induces the update of the remaining time in the UI
127        self.labeltimer = QtCore.QTimer(self)
128        self.labeltimer.timeout.connect(self.UpdateLabel)
129        self.labeltimer.setSingleShot(False)
130
131        # Update in the UI will be performed at each 1/10 of the update interval
132        self.labeltimer.start(update_frequency/10)   
133        self.label.setText("Next update in " + str(update_frequency/1000/60) + "min")
134
135        # Update the list now
136        self.Refresh()
137       
138
139    # Add a custom context menu
140    def OpenContextMenu(self, position):
141        menu = QtGui.QMenu()
142       
143        # "Show details" -> fetch details for the selected job
144        detailsjobAction = menu.addAction('Show details')     
145        detailsjobAction.setStatusTip('Display detailed info for job')
146        detailsjobAction.triggered.connect(self.ShowDetails)
147
148        # "Cancel job" -> remove job from queuing system
149        canceljobAction = menu.addAction('Cancel job')
150        canceljobAction.setStatusTip('Remove job from queueing system')
151        canceljobAction.triggered.connect(self.CancelJob)
152       
153        # "Force stop" -> remove job from queuing system
154        stopjobAction = menu.addAction('Force stop')
155        stopjobAction.setStatusTip('Terminate job properly')
156        stopjobAction.triggered.connect(self.DoStop)
157   
158        # "Force restart" -> remove job from queuing system
159        restartjobAction = menu.addAction('Force restart')
160        restartjobAction.setStatusTip('Terminate job properly and initiate restart')
161        restartjobAction.triggered.connect(self.DoRestart)
162 
163        # "Remove from list" -> remove a completed job from the list
164        removefromlistAction = menu.addAction('Remove from list')     
165        removefromlistAction.setStatusTip('Remove finished job')
166        removefromlistAction.triggered.connect(lambda: self.RemoveFromList(-1))     
167
168       
169        # Activate/deactive contect menu items based on the status of the runs
170        state = self.table.item(self.table.currentRow(),3).text()
171        if (state == "Canceled" or state == "Completed" or state == "Terminated"):
172            detailsjobAction.setEnabled(False)
173            canceljobAction.setEnabled(False) 
174            removefromlistAction.setEnabled(True) 
175        else:
176            detailsjobAction.setEnabled(True)
177            canceljobAction.setEnabled(True) 
178            removefromlistAction.setEnabled(False)   
179 
180        if ( state == "Running" ):
181            stopjobAction.setEnabled(True) 
182            restartjobAction.setEnabled(True)   
183        else:
184            stopjobAction.setEnabled(False) 
185            restartjobAction.setEnabled(False)   
186   
187        # Show the context menu
188        action = menu.exec_(self.table.mapToGlobal(position))
189
190
191    # Collecting watchdog data and display in the UI
192    def Refresh(self):
193     
194        # Use global variables
195        global jobs_save
196        global pbars
197
198        # Deactivate timer processes until update is finished
199        # QtGui.QApplication.processEvents() updates the UI whenever needed
200        self.labeltimer.stop() 
201        self.label.setText("Updating...") 
202        QtGui.QApplication.processEvents()
203        self.setEnabled(False)
204        QtGui.QApplication.processEvents()
205
206        # Get current timestamp
207        timestamp = datetime.datetime.now().strftime("%d/%m/%Y %H:%M")
208       
209        # Open an empty file for the watchdog data       
210        file = open(palm_dir + '/.wd.newdata', 'w')
211       
212 
213        # Set all required variables to their initial values. Sorting must be
214        # disabled.
215        self.table.setRowCount(0) 
216        self.table.setSortingEnabled(False)
217        i = -1
218        job_data_list = []
219        pbars = []
220       
221        # Scan all hosts in the variable hostname. For each host perform the
222        # update loop
223        for h in range(0,len(hostname)):
224         
225            # Perform ssh command
226            host    = username[h] + "@" + hostname[h]
227            ssh = sub.Popen(["ssh", "%s" % host, "/sw/tools/python/2.7.6/generic/bin/python palm_wdd queue " + username[h]],
228                           shell=False,
229                           stdout=sub.PIPE,
230                           stderr=sub.PIPE)
231            result = ssh.stdout.readlines()
232            result = filter(None, result)
233 
234 
235            # Delete all job data
236            job_data_tmp = []
237            job_data = []
238            job_data_n = []   
239            job_data_old = []
240            job_data_old_n = []
241            job_progress = 0
242
243            # In case of errors display error message
244            if ( len(result) < 1 ):
245                error = ssh.stderr.readlines()
246                if ( error != [] ):
247                    notify = QtGui.QMessageBox.warning(self,'Collect data',"Error. An error occured during read of job data for user " + username[h] +" for host " + description[h] + ".\n\nError message:\n" + ''.join(error))
248
249            # No error -> save job data
250            else:       
251
252                # Successively write to job_data
253                for j in range(0,len(result)):
254   
255                    job_data_tmp.append(j)
256                    job_data_tmp[j] = result[j].split(" ")
257                    job_data_tmp[j] = filter(None, job_data_tmp[j])
258 
259                    job_data.append(j)   
260                    job_data[j] = [job_data_tmp[j][0], description[h], job_data_tmp[j][2],                 
261                                   job_data_tmp[j][3], int(float(job_data_tmp[j][4])*100), job_data_tmp[j][5], 
262                                   job_data_tmp[j][1], job_data_tmp[j][6].rstrip()]
263                    job_data_n.append(j)
264                    job_data_n[j] = job_data_tmp[j][1]
265
266            del(result)
267
268
269
270            # Now read the data from the last update from file. These data are
271            # already in the prefered format
272            file2 = open(palm_dir + '/.wd.olddata', 'r')
273            result = file2.readlines()
274            file2.close()
275           
276            for j in range(0,len(result)):
277                if ( result[j].split()[1] == description[h] ):
278                    job_data_old.append(j)
279                    job_data_old[j] = result[j].split(" ")
280                    job_data_old[j] = filter(None, job_data_old[j])
281                    job_data_old[j] = [line.rstrip('\n') for line in job_data_old[j]]
282               
283                    job_data_old_n.append(j)
284                    job_data_old_n[j] = job_data_old[j][6]
285
286            # Merge the job_data and job_data_old to find completed, new and
287            # still queued jobs     
288            if ( len(job_data_n) > 0 and len(job_data_old_n) > 0 ):
289               jobs_full  = list(set(job_data_old_n) | set(job_data_n))
290               jobs_known    = list(set(job_data_old_n) & set(job_data_n))
291               jobs_complete = set(job_data_old_n) - set(job_data_n)
292               jobs_new      = set(job_data_n) - set(job_data_old_n)
293            elif ( len(job_data_n) > 0 ):
294               jobs_full  = job_data_n
295               jobs_known    = []
296               jobs_new = job_data_n
297               jobs_complete = []
298            elif ( len(job_data_old_n) > 0 ):
299               jobs_full  = job_data_old_n
300               jobs_known    = []
301               jobs_new = []
302               jobs_complete = job_data_old_n   
303            else:
304               jobs_full  = []
305               jobs_known    = []         
306               jobs_new = []
307               jobs_complete = []
308
309            # Display all known jobs
310            to_display = [list(job_data_n).index(item) for item in list(jobs_known) if list(jobs_known) and list(job_data_n)]
311            for j in range(0,len(to_display)):
312                i = i + 1
313                self.table.insertRow(i)
314                item = QtGui.QTableWidgetItem(job_data[to_display[j]][0])
315                item.setToolTip("Queuing name: " + job_data[to_display[j]][6])
316                self.table.setItem(i, 0, item)           
317                self.table.setItem(i, 1, QtGui.QTableWidgetItem(job_data[to_display[j]][1])) 
318                self.table.setItem(i, 2, QtGui.QTableWidgetItem(job_data[to_display[j]][2]))   
319                self.table.setItem(i, 3, QtGui.QTableWidgetItem(job_data[to_display[j]][3]))
320                item = QtGui.QTableWidgetItem(job_data[to_display[j]][5])
321                item.setToolTip("Estimated job start: " + job_data[to_display[j]][7])               
322                self.table.setItem(i, 5, item) 
323                self.table.setItem(i, 6, QtGui.QTableWidgetItem(job_data[to_display[j]][6])) 
324                self.table.item(i,2).setTextAlignment(QtCore.Qt.AlignRight)
325                self.table.item(i,5).setTextAlignment(QtCore.Qt.AlignRight)
326                pbars.append(i)
327                pbars[i] = QtGui.QProgressBar(self)
328                pbars[i].setValue(int(job_data[to_display[j]][4])) 
329 
330                # Apply a color depending on the status of the job
331                if ( job_data[to_display[j]][3] == "Running" ):
332                    self.table.setCellWidget(i,4,pbars[j]) 
333                    self.table.item(i,0).setBackground(QtGui.QColor(255, 251, 168))
334                    self.table.item(i,1).setBackground(QtGui.QColor(255, 251, 168))
335                    self.table.item(i,2).setBackground(QtGui.QColor(255, 251, 168))
336                    self.table.item(i,3).setBackground(QtGui.QColor(255, 251, 168))
337                    self.table.item(i,5).setBackground(QtGui.QColor(255, 251, 168))
338                    self.table.item(i,6).setBackground(QtGui.QColor(255, 251, 168))
339                else:
340                    pbars[j].setEnabled(False)
341                    self.table.setCellWidget(i,4,pbars[j])
342                    self.table.item(i,0).setBackground(QtGui.QColor(255, 112, 118))
343                    self.table.item(i,1).setBackground(QtGui.QColor(255, 112, 118))
344                    self.table.item(i,2).setBackground(QtGui.QColor(255, 112, 118))
345                    self.table.item(i,3).setBackground(QtGui.QColor(255, 112, 118))
346                    self.table.item(i,5).setBackground(QtGui.QColor(255, 112, 118))
347                    self.table.item(i,6).setBackground(QtGui.QColor(255, 112, 118))
348               
349                # Save the job data to file
350                job_data_list.append(i)
351                job_data_list[i] = job_data[to_display[j]][0]
352               
353                printstring = str(job_data[to_display[j]][0]) + " " + \
354                              str(job_data[to_display[j]][1]) + " " + \
355                              str(job_data[to_display[j]][2]) + " " + \
356                              str(job_data[to_display[j]][3]) + " " + \
357                              str(job_data[to_display[j]][4]) + " " + \
358                              str(job_data[to_display[j]][5]) + " " + \
359                              str(job_data[to_display[j]][6]) + " " + \
360                              str(job_data[to_display[j]][7]) + "\n"
361                file.write(printstring)
362
363
364            # Display all new jobs
365            to_display = [list(job_data_n).index(item) for item in list(jobs_new) if list(jobs_new) and list(job_data_n)]
366            for j in range(0,len(to_display)):
367                i = i + 1
368                self.table.insertRow(i)
369                item = QtGui.QTableWidgetItem(job_data[to_display[j]][0])
370                item.setToolTip("Queuing name: " + job_data[to_display[j]][6])
371                self.table.setItem(i, 0, item)   
372                self.table.setItem(i, 0, QtGui.QTableWidgetItem(job_data[to_display[j]][0]))           
373                self.table.setItem(i, 1, QtGui.QTableWidgetItem(job_data[to_display[j]][1])) 
374                self.table.setItem(i, 2, QtGui.QTableWidgetItem(job_data[to_display[j]][2]))   
375                self.table.setItem(i, 3, QtGui.QTableWidgetItem(job_data[to_display[j]][3])) 
376                item = QtGui.QTableWidgetItem(job_data[to_display[j]][5])
377                item.setToolTip("Estimated job start: " + job_data[to_display[j]][7])               
378                self.table.setItem(i, 5, item) 
379                self.table.setItem(i, 6, QtGui.QTableWidgetItem(job_data[to_display[j]][6])) 
380                self.table.item(i,2).setTextAlignment(QtCore.Qt.AlignRight)
381                self.table.item(i,5).setTextAlignment(QtCore.Qt.AlignRight)
382               
383                pbars.append(i)
384                pbars[i] = QtGui.QProgressBar(self)
385                pbars[i].setValue(int(job_data[to_display[j]][4]))   
386
387                # Apply a color depending on the status of the job
388                if ( job_data[to_display[j]][3] == "Running" ):
389                    self.table.setCellWidget(i,4,pbars[i])           
390                    self.table.item(i,0).setBackground(QtGui.QColor(255, 251, 168))
391                    self.table.item(i,1).setBackground(QtGui.QColor(255, 251, 168))
392                    self.table.item(i,2).setBackground(QtGui.QColor(255, 251, 168))
393                    self.table.item(i,3).setBackground(QtGui.QColor(255, 251, 168))
394                    self.table.item(i,5).setBackground(QtGui.QColor(255, 251, 168))
395                    self.table.item(i,6).setBackground(QtGui.QColor(255, 251, 168))
396                else:
397                    pbars[j].setEnabled(False)
398                    self.table.setCellWidget(i,4,pbars[i])
399                    self.table.item(i,0).setBackground(QtGui.QColor(255, 112, 118))
400                    self.table.item(i,1).setBackground(QtGui.QColor(255, 112, 118))
401                    self.table.item(i,2).setBackground(QtGui.QColor(255, 112, 118))
402                    self.table.item(i,3).setBackground(QtGui.QColor(255, 112, 118))
403                    self.table.item(i,5).setBackground(QtGui.QColor(255, 112, 118))
404                    self.table.item(i,6).setBackground(QtGui.QColor(255, 112, 118))
405         
406                # Save job data to file
407                job_data_list.append(i)
408                job_data_list[i] = job_data[to_display[j]][0]
409               
410                printstring = str(job_data[to_display[j]][0]) + " " + \
411                              str(job_data[to_display[j]][1]) + " " + \
412                              str(job_data[to_display[j]][2]) + " " + \
413                              str(job_data[to_display[j]][3]) + " " + \
414                              str(job_data[to_display[j]][4]) + " " + \
415                              str(job_data[to_display[j]][5]) + " " + \
416                              str(job_data[to_display[j]][6]) + " " + \
417                              str(job_data[to_display[j]][7]) + "\n"
418                file.write(printstring)
419
420
421            # Display all completed/canceled/aborted jobs. The watchdog cannot
422            # distinguish why the job has been finished
423            to_display = [list(job_data_old_n).index(item) for item in list(jobs_complete) if list(jobs_complete) and list(job_data_old_n)]
424            for j in range(0,len(to_display)):
425                i = i + 1
426                self.table.insertRow(i)
427                item = QtGui.QTableWidgetItem(job_data_old[to_display[j]][0])
428                item.setToolTip("Queuing name: " + job_data_old[to_display[j]][6])
429                self.table.setItem(i, 0, item)         
430                self.table.setItem(i, 1, QtGui.QTableWidgetItem(job_data_old[to_display[j]][1])) 
431                self.table.setItem(i, 2, QtGui.QTableWidgetItem(job_data_old[to_display[j]][2]))   
432                self.table.setItem(i, 3, QtGui.QTableWidgetItem(job_data_old[to_display[j]][3])) 
433                pbars.append(i)
434                pbars[j] = QtGui.QProgressBar(self)
435                pbars[j].setValue(int(job_data_old[to_display[j]][4])) 
436                pbars[j].setEnabled(False)
437                self.table.setCellWidget(i,4,pbars[j]) 
438                item = QtGui.QTableWidgetItem(job_data_old[to_display[j]][5])
439                item.setToolTip("Estimated job start: " + job_data_old[to_display[j]][7])               
440                self.table.setItem(i, 5, item) 
441                self.table.setItem(i, 6, QtGui.QTableWidgetItem(job_data_old[to_display[j]][6])) 
442                self.table.item(i,2).setTextAlignment(QtCore.Qt.AlignRight)
443                self.table.item(i,5).setTextAlignment(QtCore.Qt.AlignRight)
444                self.table.setItem(i, 3, QtGui.QTableWidgetItem("Completed"))
445               
446                # Apply a color depending on the status of the job
447                self.table.item(i,0).setBackground(QtGui.QColor(172, 252, 175))
448                self.table.item(i,1).setBackground(QtGui.QColor(172, 252, 175))
449                self.table.item(i,2).setBackground(QtGui.QColor(172, 252, 175))
450                self.table.item(i,3).setBackground(QtGui.QColor(172, 252, 175))
451                self.table.item(i,5).setBackground(QtGui.QColor(172, 252, 175))
452                self.table.item(i,6).setBackground(QtGui.QColor(172, 252, 175))
453
454         
455                # Save job data to file
456                job_data_list.append(i)
457                job_data_list[i] = job_data_old[to_display[j]][0]
458
459                printstring = str(job_data_old[to_display[j]][0]) + " " + \
460                              str(job_data_old[to_display[j]][1]) + " " + \
461                              str(job_data_old[to_display[j]][2]) + " " + \
462                              str(job_data_old[to_display[j]][3]) + " " + \
463                              str(job_data_old[to_display[j]][4]) + " " + \
464                              str(job_data_old[to_display[j]][5]) + " " + \
465                              str(job_data_old[to_display[j]][6]) + " " + \
466                              str(job_data_old[to_display[j]][7]) + "\n"
467                file.write(printstring)
468
469            del(jobs_complete)
470            del(jobs_new)
471            del(result)
472
473        file.close()
474
475       
476        # Update is complete, sorting can thus be re-enabled               
477        self.table.setSortingEnabled(True) 
478
479        # Update the logfile
480        if ( os.path.isfile(palm_dir + '/.wd.newdata') ):
481            shutil.copy(palm_dir + '/.wd.newdata',palm_dir + '/.wd.olddata')
482
483        # Re-enable timer processes             
484        self.setEnabled(True)
485        self.label2.setText("Last update: " + timestamp)
486        self.label.setText("Update complete.")
487        self.timetimer.restart()
488        self.timer.start()
489        self.labeltimer.start()
490        QtGui.QApplication.processEvents()
491       
492    # Canceling selected job from table
493    def CancelJob(self):
494
495        # Return internal jobname
496        jobname = self.table.item(self.table.currentRow(),6).text()
497 
498        # Check description of job in order to login on the correct host
499        descr = self.table.item(self.table.currentRow(),1).text()
500        for h in range(0,len(description)):
501            if ( descr == description[h] ):
502                host = username[h] + "@" + hostname[h]
503
504        ssh = sub.Popen(["ssh", "%s" % host, "/sw/tools/python/2.7.6/generic/bin/python palm_wdd cancel " + jobname],
505                           shell=False,
506                           stdout=sub.PIPE,
507                           stderr=sub.PIPE)
508        result = ssh.stdout.readlines()
509        result = filter(None, result)
510       
511        # In case of error display a warning message
512        if ( len(result) == 0 ):
513            error = ssh.stderr.readlines()
514            notify = QtGui.QMessageBox.warning(self,'Cancel job',"Error. Could not cancel job " + jobname + ".\n\nError message:\n" + ''.join(error))
515
516        # Otherwise inform the user and mark the job in the table
517        else:
518            self.table.setItem(self.table.currentRow(),3,QtGui.QTableWidgetItem("Canceled"))
519            notify = QtGui.QMessageBox.information(self,'Cancel job',"Job" + jobname + " canceled!\n\nServer message:\n" + ''.join(result))
520
521
522    # Show detailed information on job. For documentation see above
523    def ShowDetails(self):
524
525        jobname = self.table.item(self.table.currentRow(),6).text()
526        descr   = self.table.item(self.table.currentRow(),1).text()
527        for h in range(0,len(description)):
528            if ( descr == description[h] ):
529                host = username[h] + "@" + hostname[h]
530
531        ssh = sub.Popen(["ssh", "%s" % host, "/sw/tools/python/2.7.6/generic/bin/python palm_wdd check " + jobname],
532                           shell=False,
533                           stdout=sub.PIPE,
534                           stderr=sub.PIPE)
535        result = ssh.stdout.readlines()
536        result = filter(None, result)
537
538        if ( len(result) == 0 ):
539            error = ssh.stderr.readlines()
540            notify = QtGui.QMessageBox.warning(self,'Show job details',"Error. Could not fetch job details for " + jobname + ".\n\nError message:\n" + ''.join(error))
541        else:
542            notify = QtGui.QMessageBox.information(self,'Job details',"Details for job " + jobname + ":\n\n" + ''.join(result))
543
544
545    # Perform a forced stop on the job
546    def DoStop(self):
547
548        # Return internal jobname
549        jobname = self.table.item(self.table.currentRow(),6).text()
550 
551        # Check description of job in order to login on the correct host
552        descr = self.table.item(self.table.currentRow(),1).text()
553        for h in range(0,len(description)):
554            if ( descr == description[h] ):
555                host = username[h] + "@" + hostname[h]
556                user = username[h]
557
558        ssh = sub.Popen(["ssh", "%s" % host, "/sw/tools/python/2.7.6/generic/bin/python palm_wdd stop " + user + " " + jobname],
559                           shell=False,
560                           stdout=sub.PIPE,
561                           stderr=sub.PIPE)
562        result = ssh.stdout.readlines()
563        result = filter(None, result) 
564       
565        # In case of error display a warning message
566        if ( len(result) == 0 ):
567            error = ssh.stderr.readlines()
568            notify = QtGui.QMessageBox.warning(self,'Proper termination of job',"Error. Could not stop job " + jobname + ".\n\nError message:\n" + ''.join(error))
569
570        # Otherwise inform the user and mark the job in the table
571        else:
572            self.table.setItem(self.table.currentRow(),3,QtGui.QTableWidgetItem("Terminated"))
573            notify = QtGui.QMessageBox.information(self,'Terminatie job',"Termination of job " + jobname + " was initiated!\n\nServer message:\n" + ''.join(result))
574
575
576    # Perform a forced stop on the job
577    def DoRestart(self):
578
579        # Return internal jobname
580        jobname = self.table.item(self.table.currentRow(),6).text()
581 
582        # Check description of job in order to login on the correct host
583        descr = self.table.item(self.table.currentRow(),1).text()
584        for h in range(0,len(description)):
585            if ( descr == description[h] ):
586                host = username[h] + "@" + hostname[h]
587                user = username[h]
588
589        ssh = sub.Popen(["ssh", "%s" % host, "/sw/tools/python/2.7.6/generic/bin/python palm_wdd restart " + user + " " + jobname],
590                           shell=False,
591                           stdout=sub.PIPE,
592                           stderr=sub.PIPE)
593        result = ssh.stdout.readlines()
594        result = filter(None, result)
595       
596        # In case of error display a warning message
597        if ( len(result) == 0 ):
598            error = ssh.stderr.readlines()
599            notify = QtGui.QMessageBox.warning(self,'Proper termination of job',"Error. Could not stop job " + jobname + ".\n\nError message:\n" + ''.join(error))
600
601        # Otherwise inform the user and mark the job in the table
602        else:
603            self.table.setItem(self.table.currentRow(),3,QtGui.QTableWidgetItem("Terminated"))
604            notify = QtGui.QMessageBox.information(self,'Terminate job for restart',"Restart for job" + jobname + " was initiated!\n\nServer message:\n" + ''.join(result))
605           
606
607    # Remove a job from list - removes the current row from the table and from
608    # save file
609    def RemoveFromList(self, row):
610        if ( row == -1 ):
611            row = self.table.currentRow()
612
613        # Read data from save file
614        job_to_delete = self.table.item(row,6).text()
615        self.table.removeRow(row)
616        file = open(palm_dir + '/.wd.olddata', 'r')
617        result = file.readlines()
618        result = filter(None, result)
619        file.close()
620        file = open(palm_dir + '/.wd.olddata', 'w')
621       
622        job_data_old = []
623       
624        if ( len(result) == 0 ):
625            notify = QtGui.QMessageBox.warning(self,'Read from .wd.olddata',"Error message:\n\nCould not read from file. I/O error.")
626        else: 
627            # Save data in array job_data_old
628            for j in range(0,len(result)):
629                job_data_old.append(j)
630                job_data_old[j] = result[j].split(" ")
631                job_data_old[j] = filter(None, job_data_old[j])
632                job_data_old[j] = [line.rstrip('\n') for line in job_data_old[j]]
633               
634                # Check if line j is the selected job, if not -> save to file
635                if ( job_data_old[j][6] != job_to_delete ):
636                    printstring = str(job_data_old[j][0]) + " " + \
637                                  str(job_data_old[j][1]) + " " + \
638                                  str(job_data_old[j][2]) + " " + \
639                                  str(job_data_old[j][3]) + " " + \
640                                  str(job_data_old[j][4]) + " " + \
641                                  str(job_data_old[j][5]) + " " + \
642                                  str(job_data_old[j][6]) + " " + \
643                                  str(job_data_old[j][7]) + "\n"
644                    file.write(printstring)
645           
646        file.close() 
647
648    # Remove all completed jobs from list
649    def ClearList(self):
650     
651       num_of_lines = self.table.rowCount()
652       
653       # Delete all lines with completed/canceled jobs from list. The counter
654       # must decrease as the line numbers would be messed up otherwise
655       for j in range(num_of_lines-1,-1,-1): 
656           state = self.table.item(j,3).text()
657           if ( state == "Completed" or state == "Canceled" or state == "Terminated"):
658              self.RemoveFromList(j)
659         
660    # Update the label
661    def UpdateLabel(self):
662        remaining_time = (update_frequency - self.timetimer.elapsed()) / 1000 / 60
663        self.label.setText("Next update in " + str(remaining_time) + " min")
664       
665
666# Main loop       
667def main():
668   
669    app = QtGui.QApplication(sys.argv)
670    res = Watchdog() 
671    sys.exit(app.exec_())
672
673
674if __name__ == '__main__':
675    main()   
Note: See TracBrowser for help on using the repository browser.