netflow: Correctly track flow creation time.
[cascardo/ovs.git] / ovsdb / ovsdbmonitor / OVECommonWindow.py
1 # Copyright (c) 2010 Citrix Systems, Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at:
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from OVEStandard import *
16 from OVEConfig import *
17 from OVEFetch import *
18 from OVELogger import *
19 from OVEUtil import *
20
21 from Ui_MainWindow import *
22
23 class OVECommonWindow:
24     def __init__(self, app, loadIndex = None):
25         self.app = app
26         self.intervalTimerId = None        
27         self.hostUuid = ''
28         self.intervalChecked = True
29         self.intervalSeconds = 5
30         self.fetchSkip = 0
31         self.currentRef = self.BASE_REF
32                 
33         self.ui.setupUi(self)
34         
35         if loadIndex is not None:
36             self.loadSettings(loadIndex)
37         
38         self.connect(self.ui.actionNew_DB_Window, QtCore.SIGNAL("triggered()"), self.xon_actionNew_DB_Window_triggered)
39         self.connect(self.ui.actionNew_Flow_Window, QtCore.SIGNAL("triggered()"), self.xon_actionNew_Flow_Window_triggered)
40         self.connect(self.ui.actionShow_Log, QtCore.SIGNAL("triggered()"), self.xon_actionShow_Log_triggered)
41         self.connect(self.ui.actionPreferences, QtCore.SIGNAL("triggered()"), self.xon_actionPreferences_triggered)
42         self.connect(self.ui.actionQuit, QtCore.SIGNAL("triggered()"), self.xon_actionQuit_triggered)
43         self.connect(self.ui.fetchButton, QtCore.SIGNAL("clicked()"), self.xon_fetchButton_clicked)
44         self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.xon_tabWidget_currentChanged)
45         self.connect(self.ui.hostComboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.xon_hostComboBox_currentIndexChanged)
46         self.connect(self.ui.intervalCheckBox, QtCore.SIGNAL("stateChanged(int)"), self.xon_intervalCheckBox_stateChanged)
47         self.connect(self.ui.intervalSpinBox, QtCore.SIGNAL("valueChanged(int)"), self.xon_intervalSpinBox_valueChanged)
48         self.connect(OVEConfig.Inst(), QtCore.SIGNAL("configUpdated()"), self.xon_configUpdated)
49         
50         self.updateHosts()
51         self.updateInterval()
52         self.updateIntervalState()
53         self.updateTable()
54         
55     def xon_actionNew_DB_Window_triggered(self):
56         self.app.newMainWindow()
57  
58     def xon_actionNew_Flow_Window_triggered(self):
59         self.app.newFlowWindow()
60
61     def xon_actionShow_Log_triggered(self):
62         self.app.showLog(True)
63
64     def xon_actionPreferences_triggered(self):
65         self.app.showConfig(True)
66
67     def xon_actionQuit_triggered(self):
68         self.app.quit()
69     
70     def xon_tabWidget_currentChanged(self, value):
71         self.updateTable()
72         
73     def xon_fetchButton_clicked(self):
74         self.updateTable()
75     
76     def xon_configUpdated(self):
77         self.updateHosts()
78     
79     def xon_hostComboBox_currentIndexChanged(self, index):
80         if (index >= 0):
81             itemData = self.ui.hostComboBox.itemData(index)
82             self.hostUuid = str(itemData.toString())
83             self.deleteCurrentTable()
84             self.updateTable()
85     
86     def xon_intervalCheckBox_stateChanged(self, state):
87         self.intervalChecked = (state == Qt.Checked)
88         self.updateIntervalState()
89     
90     def xon_intervalSpinBox_valueChanged(self, value):
91         self.intervalSeconds = value
92         self.updateIntervalState()
93     
94     def updateIntervalState(self):
95         if self.intervalTimerId is not None:
96             self.killTimer(self.intervalTimerId)
97         if self.intervalChecked:
98             self.intervalTimerId = self.startTimer(1000*self.intervalSeconds)
99     
100     def updateHosts(self):
101         currentHostUuid = self.hostUuid # self.hostUuid will change due to currentIndexChanged events as we rebuild the combo box
102         self.hostUuid = ''
103         self.ui.hostComboBox.clear()
104         for i, host in enumerate(OVEConfig.Inst().hosts):
105             self.ui.hostComboBox.addItem(host['address'], QVariant(host['uuid']))
106             if host['uuid'] == currentHostUuid:
107                 # This is the currently selected host
108                 self.ui.hostComboBox.setCurrentIndex(i)
109         if len(OVEConfig.Inst().hosts) == 0:
110             self.ui.hostComboBox.addItem('(No hosts configured)', QVariant(''))
111             
112     def updateInterval(self):
113         self.ui.intervalCheckBox.setChecked(self.intervalChecked)
114         self.ui.intervalSpinBox.setValue(self.intervalSeconds)
115  
116     def handleFetchEvent(self, ref, values):
117         OVELog('Unhandled FetchEvent')
118  
119     def handleFetchFailEvent(self, ref, message):
120         OVELog('Unhandled FetchFailEvent')
121  
122     def setFetchSkip(self):
123         # Call before sending a request via OVEFetch
124         self.fetchSkip = 6
125  
126     def timerEvent(self, event):
127         if event.timerId() == self.intervalTimerId:
128             if self.fetchSkip > 0:
129                 self.statusBar().showMessage('Fetch stalled... resend in '+str(self.fetchSkip*self.intervalSeconds)+'s') 
130                 self.fetchSkip -= 1
131                 if self.fetchSkip == 0:
132                     # Stall has timed out. The connection might have hung so reset.  Seems to happen with PySide only
133                     OVEFetch.Inst(self.hostUuid).resetTransport()
134             else:
135                 self.updateTable()
136         else:
137             QtGui.QMainWindow.timerEvent(self, event)
138  
139     def customEvent(self, event):
140         if event.type() == OVEFetchEvent.TYPE:
141             if isinstance(event, OVEFetchEvent):
142                 # The right way to get data
143                 ref = event.ref
144                 values = event.data
145             else:
146                 # Workaround for PySide issue
147                 ref = OVEFetch.Inst(self.hostUuid).snoopRef(self)
148                 values = OVEFetch.Inst(self.hostUuid).snoopValues(self)
149             try:
150                 if ref == self.currentRef:
151                     self.fetchSkip = 0
152                     self.currentRef += 1 # PySide workaround
153                     self.handleFetchEvent(ref, values)
154                 else:
155                     # If refs don't match this event relates to a request before the current one.  We've moved
156                     # on since then, e.g. changed the table we've viewing, so ignore it
157                     if OVEConfig.Inst().logTraffic:
158                         OVELog('FetchEvent ref mismatch '+str(ref)+' != '+str(self.currentRef))
159             except Exception, e:
160                 OVELog("Error during data handling: "+str(e))
161
162         elif event.type() == OVEFetchFailEvent.TYPE:
163             if isinstance(event, OVEFetchFailEvent):
164                 # The right way to get data
165                 ref = event.ref
166                 message = event.message
167             else:
168                 # Workaround for PySide issue
169                 ref = OVEFetch.Inst(self.hostUuid).snoopRef(self)
170                 message = OVEFetch.Inst(self.hostUuid).snoopMessage(self)
171             if message is not None:
172                 OVELog(message)
173             if ref == self.currentRef:
174                 self.fetchSkip = 0
175                 self.currentRef += 1 # PySide workaround
176                 self.handleFetchFailEvent(ref, message)
177             else:
178                 if OVEConfig.Inst().logTraffic:
179                     OVELog('FetchFailEvent ref mismatch '+str(ref)+' != '+str(self.currentRef))
180  
181     def deleteCurrentTable(self):
182         pass
183  
184     def saveSettings(self, index):
185         key = self.LOAD_KEY+str(index)
186         settings = QtCore.QSettings()
187         settings.setValue(key+"/loadable", QVariant(True))
188         settings.setValue(key+"/pos", QVariant(self.pos()))
189         settings.setValue(key+"/size", QVariant(self.size()))
190         settings.setValue(key+"/hostUuid", QVariant(self.hostUuid))
191         settings.setValue(key+"/intervalChecked", QVariant(self.intervalChecked))
192         settings.setValue(key+"/intervalSeconds", QVariant(self.intervalSeconds))
193
194         return settings, key
195     
196     def loadSettings(self, index):
197         key = self.LOAD_KEY+str(index)
198         settings = QtCore.QSettings()
199         pos = settings.value(key+"/pos", QVariant(QtCore.QPoint(200, 200))).toPoint()
200         size = settings.value(key+"/size", QVariant(QtCore.QSize(400, 400))).toSize();
201
202         self.hostUuid = str(settings.value(key+"/hostUuid", QVariant('Unloaded')).toString())
203         self.intervalChecked = settings.value(key+"/intervalChecked", QVariant(True)).toBool()
204         self.intervalSeconds = settings.value(key+"/intervalSeconds", QVariant(5)).toInt()[0]
205         self.resize(size)
206         self.move(pos)
207         return settings, key
208
209     @classmethod
210     def terminateSettings(self, index):
211         key = self.LOAD_KEY+str(index)
212         settings = QtCore.QSettings()
213         settings.setValue(key+"/loadable", QVariant(False))
214         settings.sync()
215         
216     @classmethod
217     def isLoadable(cls, index):
218         key = cls.LOAD_KEY+str(index)
219         settings = QtCore.QSettings()
220         return settings.value(key+"/loadable", QVariant(False)).toBool()
221