2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 06:45:17 +00:00

ovsdbmonitor: Remove.

ovsdbmonitor was poorly maintained and not widely used.

Acked-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Ben Pfaff
2014-01-10 15:25:40 -08:00
parent feb8a80bb9
commit 7868fbc6c9
43 changed files with 6 additions and 3772 deletions

21
INSTALL
View File

@@ -86,11 +86,6 @@ or the database schema, you will also need the following software:
- libtool version 2.4 or later. (Older versions might work too.)
If you modify the ovsdbmonitor tool, then you will also need the
following:
- pyuic4 from PyQt4 (http://www.riverbankcomputing.co.uk).
To run the unit tests, you also need:
- Perl. Version 5.10.1 is known to work. Earlier versions should
@@ -138,22 +133,6 @@ following software:
On Linux you should ensure that /dev/urandom exists. To support TAP
devices, you must also ensure that /dev/net/tun exists.
To run the ovsdbmonitor tool, the machine must also have the following
software:
- Python 2.x, for x >= 4.
- Python Twisted Conch.
- Python JSON.
- PySide or PyQt4.
- Python Zope interface module.
(On Debian "lenny" the above can be installed with "apt-get install
python-json python-qt4 python-zopeinterface python-twisted-conch".)
Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD
=================================================================

View File

@@ -11,8 +11,7 @@ In that case, you need at least the following packages.
py27-xml
pkg_alternatives
Some components (eg. ovsdbmonitor) have additional requirements.
(See INSTALL)
Some components have additional requirements. (See INSTALL)
Assuming you are running NetBSD/amd64 6.1.2, you can download and
install pre-built binary packages as the following.

View File

@@ -1,4 +1,4 @@
# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
# Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
#
# Copying and distribution of this file, with or without modification,
# are permitted in any medium without royalty provided the copyright
@@ -139,7 +139,6 @@ SUFFIXES += .in
-e 's,[@]bindir[@],$(bindir),g' \
-e 's,[@]sbindir[@],$(sbindir),g' \
-e 's,[@]abs_top_srcdir[@],$(abs_top_srcdir),g' \
-e 's,[@]ovsdbmonitordir[@],$(ovsdbmonitordir),g' \
> $@.tmp
@if head -n 1 $@.tmp | grep '#!' > /dev/null; then \
echo chmod +x $@.tmp; \

3
NEWS
View File

@@ -1,6 +1,7 @@
Post-v2.1.0
---------------------
- The "ovsdbmonitor" graphical tool has been removed, because it was
poorly maintained and not widely used.
v2.1.0 - xx xxx xxxx
---------------------

3
README
View File

@@ -64,9 +64,6 @@ The main components of this distribution are:
* ovs-appctl, a utility that sends commands to running Open
vSwitch daemons.
* ovsdbmonitor, a GUI tool for remotely viewing OVS databases and
OpenFlow flow tables.
Open vSwitch also provides some tools:
* ovs-ofctl, a utility for querying and controlling OpenFlow

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -57,8 +57,6 @@ OVS_CHECK_NETLINK
OVS_CHECK_OPENSSL
OVS_CHECK_LOGDIR
OVS_CHECK_PYTHON
OVS_CHECK_PYUIC4
OVS_CHECK_OVSDBMONITOR
OVS_CHECK_PYTHON_COMPAT
OVS_CHECK_DOT
OVS_CHECK_IF_PACKET
@@ -132,7 +130,6 @@ AC_CONFIG_FILES(tests/atlocal)
dnl This makes sure that include/openflow gets created in the build directory.
AC_CONFIG_COMMANDS([include/openflow/openflow.h.stamp])
AC_CONFIG_COMMANDS([ovsdb/ovsdbmonitor/dummy], [:])
AC_CONFIG_COMMANDS([utilities/bugtool/dummy], [:])
AM_CONDITIONAL([LINUX_DATAPATH], [test "$HAVE_NETLINK" = yes && test "$ESX" = no])

1
debian/.gitignore vendored
View File

@@ -16,6 +16,5 @@
/openvswitch-switch
/openvswitch-switch.copyright
/openvswitch-test
/ovsdbmonitor
/python-openvswitch
/tmp

2
debian/automake.mk vendored
View File

@@ -42,8 +42,6 @@ EXTRA_DIST += \
debian/openvswitch-vtep.init \
debian/openvswitch-vtep.install \
debian/openvswitch-vtep.manpages \
debian/ovsdbmonitor.install \
debian/ovsdbmonitor.manpages \
debian/ovs-monitor-ipsec \
debian/python-openvswitch.dirs \
debian/python-openvswitch.install \

19
debian/control vendored
View File

@@ -152,25 +152,6 @@ Description: Python bindings for Open vSwitch
.
This package contains the full Python bindings for Open vSwitch database.
Package: ovsdbmonitor
Architecture: all
Section: utils
Depends: ${python:Depends}, python-openvswitch, ${misc:Depends}
Description: Open vSwitch graphical monitoring tool
Open vSwitch is a production quality, multilayer, software-based,
Ethernet virtual switch. It is designed to enable massive network
automation through programmatic extension, while still supporting
standard management interfaces and protocols (e.g. NetFlow, IPFIX,
sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
to support distribution across multiple physical servers similar to
VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
.
This package is a GUI tool for monitoring and troubleshooting local
or remote Open vSwitch installations. It presents GUI tables that
graphically represent an Open vSwitch kernel flow table (similar to
"ovs-dpctl dump-flows") and Open vSwitch database contents (similar
to "ovs-vsctl list <table>").
Package: openvswitch-test
Architecture: all
Depends: ${misc:Depends}, ${python:Depends}, python-twisted-web, python (>= 2.7) | python-argparse

View File

@@ -1,2 +0,0 @@
usr/bin/ovsdbmonitor
usr/share/ovsdbmonitor

View File

@@ -1 +0,0 @@
ovsdb/ovsdbmonitor/ovsdbmonitor.1

1
debian/rules vendored
View File

@@ -107,7 +107,6 @@ install-indep: build-indep
# And we should also clean useless license files, which are already
# descriped in our debian/copyright anyway.
rm -f debian/$(pdkms)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/COPYING \
debian/$(pdkms)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/ovsdb/ovsdbmonitor/COPYING \
debian/$(pdkms)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/xenserver/LICENSE
install-arch: build-arch

View File

@@ -1,6 +1,6 @@
# -*- autoconf -*-
# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -242,21 +242,6 @@ AC_DEFUN([OVS_CHECK_DOT],
fi])
AM_CONDITIONAL([HAVE_DOT], [test "$ovs_cv_dot" = yes])])
dnl Checks for pyuic4.
AC_DEFUN([OVS_CHECK_PYUIC4],
[AC_CACHE_CHECK(
[for pyuic4],
[ovs_cv_pyuic4],
[if (pyuic4 --version) >/dev/null 2>&1; then
ovs_cv_pyuic4=pyuic4
else
ovs_cv_pyuic4=no
fi])
AM_MISSING_PROG([PYUIC4], [pyuic4])
if test $ovs_cv_pyuic4 != no; then
PYUIC4=$ovs_cv_pyuic4
fi])
dnl Checks whether $PYTHON supports the module given as $1
AC_DEFUN([OVS_CHECK_PYTHON_MODULE],
[AC_REQUIRE([OVS_CHECK_PYTHON])
@@ -275,30 +260,6 @@ sys.exit(0)' >&AS_MESSAGE_LOG_FD 2>&1; then
fi
fi])])
dnl Checks for Python modules needed by ovsdbmonitor.
AC_DEFUN([OVS_CHECK_OVSDBMONITOR],
[OVS_CHECK_PYTHON_MODULE([PySide.QtCore])
OVS_CHECK_PYTHON_MODULE([PyQt4.QtCore])
OVS_CHECK_PYTHON_MODULE([twisted.conch.ssh])
OVS_CHECK_PYTHON_MODULE([twisted.internet])
OVS_CHECK_PYTHON_MODULE([twisted.application])
OVS_CHECK_PYTHON_MODULE([json])
OVS_CHECK_PYTHON_MODULE([zope.interface])
if (test $ovs_cv_py_PySide_QtCore = yes \
|| test $ovs_cv_py_PyQt4_QtCore = yes) \
&& test $ovs_cv_py_twisted_conch_ssh = yes \
&& test $ovs_cv_py_twisted_internet = yes \
&& test $ovs_cv_py_twisted_application = yes \
&& test $ovs_cv_py_json = yes \
&& test $ovs_cv_py_zope_interface = yes; then
BUILD_OVSDBMONITOR=yes
else
BUILD_OVSDBMONITOR=no
fi
AC_MSG_CHECKING([whether to build ovsdbmonitor])
AC_MSG_RESULT([$BUILD_OVSDBMONITOR])
AM_CONDITIONAL([BUILD_OVSDBMONITOR], [test $BUILD_OVSDBMONITOR = yes])])
dnl Checks for missing python modules at build time
AC_DEFUN([OVS_CHECK_PYTHON_COMPAT],
[OVS_CHECK_PYTHON_MODULE([uuid])

View File

@@ -101,5 +101,3 @@ EXTRA_DIST += ovsdb/ovsdb-dot.in ovsdb/dot2pic
noinst_SCRIPTS += ovsdb/ovsdb-dot
DISTCLEANFILES += ovsdb/ovsdb-dot
OVSDB_DOT = $(run_python) $(srcdir)/ovsdb/ovsdb-dot.in
include ovsdb/ovsdbmonitor/automake.mk

View File

@@ -1 +0,0 @@
/ovsdbmonitor

View File

@@ -1,13 +0,0 @@
Copyright (c) 2010 Citrix Systems, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,185 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigWindow</class>
<widget class="QDialog" name="ConfigWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>303</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="windowTitle">
<string>OVSDB Monitor Configuration</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="hosts">
<attribute name="title">
<string>Hosts</string>
</attribute>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>341</width>
<height>194</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QListWidget" name="hostList"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="hostAddButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="hostEditButton">
<property name="text">
<string>Edit</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="hostDeleteButton">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="logging">
<attribute name="title">
<string>Logging</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="logTrafficCheckBox">
<property name="toolTip">
<string>Whether to log traffic exchanges in the log window</string>
</property>
<property name="text">
<string>Log traffic</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>164</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="view">
<attribute name="title">
<string>View</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="truncateUuidsCheckBox">
<property name="toolTip">
<string>Replaces UUIDs with a shorter string of the first few characters. The tooltip still contains the full value</string>
</property>
<property name="text">
<string>Truncate UUIDs</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>164</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>hostList</tabstop>
<tabstop>hostAddButton</tabstop>
<tabstop>hostEditButton</tabstop>
<tabstop>hostDeleteButton</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>tabWidget</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -1,216 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FlowWindow</class>
<widget class="QMainWindow" name="FlowWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>OVSDB Monitor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="unset">
<attribute name="title">
<string>Awaiting update...</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10"/>
</widget>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="ssgCheckBox">
<property name="text">
<string>Server-side grep</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="ssgComboBox">
<property name="editable">
<bool>true</bool>
</property>
<property name="maxVisibleItems">
<number>20</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
<property name="minimumContentsLength">
<number>32</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ssgSaveButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ssgDeleteButton">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="hostLabel">
<property name="text">
<string>Host</string>
</property>
<property name="buddy">
<cstring>hostComboBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hostComboBox">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="intervalCheckBox">
<property name="text">
<string>Auto-refetch every</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="intervalSpinBox">
<property name="suffix">
<string>s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="fetchPathsButton">
<property name="toolTip">
<string>Refetches the datapath names and rebuilds the window tabs to reflect them. Use when the network has been reconfigured, e.g. a bond has been created</string>
</property>
<property name="text">
<string>Refetch Datapath List</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="fetchButton">
<property name="text">
<string>Refetch</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>28</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionNew_DB_Window"/>
<addaction name="actionNew_Flow_Window"/>
<addaction name="actionShow_Log"/>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionShow_Log">
<property name="text">
<string>Show Log</string>
</property>
</action>
<action name="actionNew_DB_Window">
<property name="text">
<string>New DB Window</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
</action>
<action name="actionNew_Flow_Window">
<property name="text">
<string>New Flow Window</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,145 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>HostWindow</class>
<widget class="QDialog" name="HostWindow">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Host Properties</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Host name or IP</string>
</property>
<property name="buddy">
<cstring>hostAddressEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="hostAddressEdit">
<property name="minimumSize">
<size>
<width>256</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>SSH Password</string>
</property>
<property name="buddy">
<cstring>hostPasswordEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="hostPasswordEdit">
<property name="minimumSize">
<size>
<width>256</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Connect target</string>
</property>
<property name="buddy">
<cstring>hostConnectTarget</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="hostConnectTarget">
<property name="minimumSize">
<size>
<width>256</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>hostAddressEdit</tabstop>
<tabstop>hostPasswordEdit</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>HostWindow</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>HostWindow</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LogWindow</class>
<widget class="QDialog" name="LogWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>735</width>
<height>558</height>
</rect>
</property>
<property name="windowTitle">
<string>OVSDB Monitor Log</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextBrowser" name="textBrowser"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Reset</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>LogWindow</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>LogWindow</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,253 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>OVSDB Monitor</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="Bridge">
<attribute name="title">
<string>Bridge</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTableWidget" name="BridgeTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Controller">
<attribute name="title">
<string>Controller</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTableWidget" name="ControllerTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Interface">
<attribute name="title">
<string>Interface</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QTableWidget" name="InterfaceTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Mirror">
<attribute name="title">
<string>Mirror</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QTableWidget" name="MirrorTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="NetFlow">
<attribute name="title">
<string>NetFlow</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QTableWidget" name="NetFlowTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Open_vSwitch">
<attribute name="title">
<string>Open_vSwitch</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QTableWidget" name="Open_vSwitchTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Port">
<attribute name="title">
<string>Port</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QTableWidget" name="PortTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="QoS">
<attribute name="title">
<string>QoS</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QTableWidget" name="QoSTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="Queue">
<attribute name="title">
<string>Queue</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_11">
<item row="0" column="0">
<widget class="QTableWidget" name="QueueTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="sFlow">
<attribute name="title">
<string>sFlow</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QTableWidget" name="sFlowTable"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="SSL">
<attribute name="title">
<string>SSL</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QTableWidget" name="SSLTable"/>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="hostLabel">
<property name="text">
<string>Host</string>
</property>
<property name="buddy">
<cstring>hostComboBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hostComboBox">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="intervalCheckBox">
<property name="text">
<string>Auto-refetch every</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="intervalSpinBox">
<property name="suffix">
<string>s</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="fetchButton">
<property name="text">
<string>Refetch</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>28</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionNew_DB_Window"/>
<addaction name="actionNew_Flow_Window"/>
<addaction name="actionShow_Log"/>
<addaction name="actionPreferences"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionShow_Log">
<property name="text">
<string>Show Log</string>
</property>
</action>
<action name="actionNew_DB_Window">
<property name="text">
<string>New DB Window</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
</property>
</action>
<action name="actionQuit">
<property name="text">
<string>Quit</string>
</property>
</action>
<action name="actionNew_Flow_Window">
<property name="text">
<string>New Flow Window</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,105 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from OVEStandard import *
from OVEConfig import *
from OVEFetch import *
from OVEConfigWindow import *
from OVEFlowWindow import *
from OVELogWindow import *
from OVEMainWindow import *
class OVEApp:
def __init__(self):
self.app = globalApp
self.app.setOrganizationName("Citrix_Systems_Inc")
self.app.setOrganizationDomain("citrix.com")
self.app.setApplicationName("ovsdbmonitor")
self.mainWindows = []
self.flowWindows = []
self.configWindow = None
def enter(self):
if len(OVEConfig.Inst().hosts) < 1:
self.showConfig(True)
QtGui.QMessageBox.information(
None, "OVSDB Monitor",
"This application browses openvswitch databases on remote hosts. Please add one or more openvswitch hosts to continue")
self.loadMainWindows()
self.loadFlowWindows()
if len(self.mainWindows) == 0 and len(self.flowWindows) == 0:
self.newMainWindow()
self.newLogWindow()
# Reactor must be started after the event loop is running, so use a zero timeout
QtCore.QTimer.singleShot(0, OVEFetch.startReactor)
OVELog("Application started")
retCode = self.app.exec_()
index = 0
for mainWindow in self.mainWindows:
if mainWindow.isVisible():
mainWindow.saveSettings(index)
index += 1 # Indent intentional
OVEMainWindow.terminateSettings(index)
index = 0
for flowWindow in self.flowWindows:
if flowWindow.isVisible():
flowWindow.saveSettings(index)
index += 1 # Indent intentional
OVEFlowWindow.terminateSettings(index)
self.logWindow.saveSettings()
def quit(self):
self.app.quit()
def showLog(self, value):
if value:
self.logWindow.hide()
self.logWindow.show()
else:
self.logWindow.hide()
def showConfig(self, value):
if value:
del self.configWindow
self.configWindow = OVEConfigWindow(self)
self.configWindow.show()
else:
self.configWindow.hide()
def newMainWindow(self, loadIndex = None):
self.mainWindows.append(OVEMainWindow(self, loadIndex))
self.mainWindows[-1].show()
def newFlowWindow(self, loadIndex = None):
self.flowWindows.append(OVEFlowWindow(self, loadIndex))
self.flowWindows[-1].show()
def newLogWindow(self):
self.logWindow = OVELogWindow(self)
def loadMainWindows(self):
for loadIndex in range(0, 100):
if OVEMainWindow.isLoadable(loadIndex):
self.newMainWindow(loadIndex)
else:
break
def loadFlowWindows(self):
for loadIndex in range(0, 100):
if OVEFlowWindow.isLoadable(loadIndex):
self.newFlowWindow(loadIndex)
else:
break

View File

@@ -1,221 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
from OVEFetch import *
from OVELogger import *
from OVEUtil import *
from Ui_MainWindow import *
class OVECommonWindow:
def __init__(self, app, loadIndex = None):
self.app = app
self.intervalTimerId = None
self.hostUuid = ''
self.intervalChecked = True
self.intervalSeconds = 5
self.fetchSkip = 0
self.currentRef = self.BASE_REF
self.ui.setupUi(self)
if loadIndex is not None:
self.loadSettings(loadIndex)
self.connect(self.ui.actionNew_DB_Window, QtCore.SIGNAL("triggered()"), self.xon_actionNew_DB_Window_triggered)
self.connect(self.ui.actionNew_Flow_Window, QtCore.SIGNAL("triggered()"), self.xon_actionNew_Flow_Window_triggered)
self.connect(self.ui.actionShow_Log, QtCore.SIGNAL("triggered()"), self.xon_actionShow_Log_triggered)
self.connect(self.ui.actionPreferences, QtCore.SIGNAL("triggered()"), self.xon_actionPreferences_triggered)
self.connect(self.ui.actionQuit, QtCore.SIGNAL("triggered()"), self.xon_actionQuit_triggered)
self.connect(self.ui.fetchButton, QtCore.SIGNAL("clicked()"), self.xon_fetchButton_clicked)
self.connect(self.ui.tabWidget, QtCore.SIGNAL("currentChanged(int)"), self.xon_tabWidget_currentChanged)
self.connect(self.ui.hostComboBox, QtCore.SIGNAL("currentIndexChanged(int)"), self.xon_hostComboBox_currentIndexChanged)
self.connect(self.ui.intervalCheckBox, QtCore.SIGNAL("stateChanged(int)"), self.xon_intervalCheckBox_stateChanged)
self.connect(self.ui.intervalSpinBox, QtCore.SIGNAL("valueChanged(int)"), self.xon_intervalSpinBox_valueChanged)
self.connect(OVEConfig.Inst(), QtCore.SIGNAL("configUpdated()"), self.xon_configUpdated)
self.updateHosts()
self.updateInterval()
self.updateIntervalState()
self.updateTable()
def xon_actionNew_DB_Window_triggered(self):
self.app.newMainWindow()
def xon_actionNew_Flow_Window_triggered(self):
self.app.newFlowWindow()
def xon_actionShow_Log_triggered(self):
self.app.showLog(True)
def xon_actionPreferences_triggered(self):
self.app.showConfig(True)
def xon_actionQuit_triggered(self):
self.app.quit()
def xon_tabWidget_currentChanged(self, value):
self.updateTable()
def xon_fetchButton_clicked(self):
self.updateTable()
def xon_configUpdated(self):
self.updateHosts()
def xon_hostComboBox_currentIndexChanged(self, index):
if (index >= 0):
itemData = self.ui.hostComboBox.itemData(index)
self.hostUuid = str(itemData.toString())
self.deleteCurrentTable()
self.updateTable()
def xon_intervalCheckBox_stateChanged(self, state):
self.intervalChecked = (state == Qt.Checked)
self.updateIntervalState()
def xon_intervalSpinBox_valueChanged(self, value):
self.intervalSeconds = value
self.updateIntervalState()
def updateIntervalState(self):
if self.intervalTimerId is not None:
self.killTimer(self.intervalTimerId)
if self.intervalChecked:
self.intervalTimerId = self.startTimer(1000*self.intervalSeconds)
def updateHosts(self):
currentHostUuid = self.hostUuid # self.hostUuid will change due to currentIndexChanged events as we rebuild the combo box
self.hostUuid = ''
self.ui.hostComboBox.clear()
for i, host in enumerate(OVEConfig.Inst().hosts):
self.ui.hostComboBox.addItem(host['address'], QVariant(host['uuid']))
if host['uuid'] == currentHostUuid:
# This is the currently selected host
self.ui.hostComboBox.setCurrentIndex(i)
if len(OVEConfig.Inst().hosts) == 0:
self.ui.hostComboBox.addItem('(No hosts configured)', QVariant(''))
def updateInterval(self):
self.ui.intervalCheckBox.setChecked(self.intervalChecked)
self.ui.intervalSpinBox.setValue(self.intervalSeconds)
def handleFetchEvent(self, ref, values):
OVELog('Unhandled FetchEvent')
def handleFetchFailEvent(self, ref, message):
OVELog('Unhandled FetchFailEvent')
def setFetchSkip(self):
# Call before sending a request via OVEFetch
self.fetchSkip = 6
def timerEvent(self, event):
if event.timerId() == self.intervalTimerId:
if self.fetchSkip > 0:
self.statusBar().showMessage('Fetch stalled... resend in '+str(self.fetchSkip*self.intervalSeconds)+'s')
self.fetchSkip -= 1
if self.fetchSkip == 0:
# Stall has timed out. The connection might have hung so reset. Seems to happen with PySide only
OVEFetch.Inst(self.hostUuid).resetTransport()
else:
self.updateTable()
else:
QtGui.QMainWindow.timerEvent(self, event)
def customEvent(self, event):
if event.type() == OVEFetchEvent.TYPE:
if isinstance(event, OVEFetchEvent):
# The right way to get data
ref = event.ref
values = event.data
else:
# Workaround for PySide issue
ref = OVEFetch.Inst(self.hostUuid).snoopRef(self)
values = OVEFetch.Inst(self.hostUuid).snoopValues(self)
try:
if ref == self.currentRef:
self.fetchSkip = 0
self.currentRef += 1 # PySide workaround
self.handleFetchEvent(ref, values)
else:
# If refs don't match this event relates to a request before the current one. We've moved
# on since then, e.g. changed the table we've viewing, so ignore it
if OVEConfig.Inst().logTraffic:
OVELog('FetchEvent ref mismatch '+str(ref)+' != '+str(self.currentRef))
except Exception, e:
OVELog("Error during data handling: "+str(e))
elif event.type() == OVEFetchFailEvent.TYPE:
if isinstance(event, OVEFetchFailEvent):
# The right way to get data
ref = event.ref
message = event.message
else:
# Workaround for PySide issue
ref = OVEFetch.Inst(self.hostUuid).snoopRef(self)
message = OVEFetch.Inst(self.hostUuid).snoopMessage(self)
if message is not None:
OVELog(message)
if ref == self.currentRef:
self.fetchSkip = 0
self.currentRef += 1 # PySide workaround
self.handleFetchFailEvent(ref, message)
else:
if OVEConfig.Inst().logTraffic:
OVELog('FetchFailEvent ref mismatch '+str(ref)+' != '+str(self.currentRef))
def deleteCurrentTable(self):
pass
def saveSettings(self, index):
key = self.LOAD_KEY+str(index)
settings = QtCore.QSettings()
settings.setValue(key+"/loadable", QVariant(True))
settings.setValue(key+"/pos", QVariant(self.pos()))
settings.setValue(key+"/size", QVariant(self.size()))
settings.setValue(key+"/hostUuid", QVariant(self.hostUuid))
settings.setValue(key+"/intervalChecked", QVariant(self.intervalChecked))
settings.setValue(key+"/intervalSeconds", QVariant(self.intervalSeconds))
return settings, key
def loadSettings(self, index):
key = self.LOAD_KEY+str(index)
settings = QtCore.QSettings()
pos = settings.value(key+"/pos", QVariant(QtCore.QPoint(200, 200))).toPoint()
size = settings.value(key+"/size", QVariant(QtCore.QSize(400, 400))).toSize();
self.hostUuid = str(settings.value(key+"/hostUuid", QVariant('Unloaded')).toString())
self.intervalChecked = settings.value(key+"/intervalChecked", QVariant(True)).toBool()
self.intervalSeconds = settings.value(key+"/intervalSeconds", QVariant(5)).toInt()[0]
self.resize(size)
self.move(pos)
return settings, key
@classmethod
def terminateSettings(self, index):
key = self.LOAD_KEY+str(index)
settings = QtCore.QSettings()
settings.setValue(key+"/loadable", QVariant(False))
settings.sync()
@classmethod
def isLoadable(cls, index):
key = cls.LOAD_KEY+str(index)
settings = QtCore.QSettings()
return settings.value(key+"/loadable", QVariant(False)).toBool()

View File

@@ -1,101 +0,0 @@
# Copyright (c) 2011 Nicira, Inc.
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVELogger import *
import ovs.json
def str_recursive(x):
t = type(x)
if t == unicode:
return str(x)
elif t == list:
return [str_recursive(_) for _ in x]
elif t == dict:
out = {}
for k,v in x.iteritems():
out[str_recursive(k)] = str_recursive(v)
return out
else:
return x
class OVEConfig(QtCore.QObject):
instance = None
def __init__(self):
QtCore.QObject.__init__(self)
self.hosts = []
self.logTraffic = True
self.truncateUuids = True
self.ssgList = []
@classmethod
def Inst(cls):
if cls.instance is None:
cls.instance = OVEConfig()
cls.instance.loadConfig()
return cls.instance
def hostFromUuid(self, uuid):
for host in self.hosts:
if host['uuid'] == uuid:
return host
OVELog("+++ Couldn't find host '"+str(uuid)+"' in "+str([x['uuid'] for x in self.hosts]))
return None
def saveConfig(self):
settings = QtCore.QSettings()
settings.setValue('config/hosts', QVariant(ovs.json.to_string((self.hosts))))
settings.setValue('config/logTraffic', QVariant(self.logTraffic))
settings.setValue('config/truncateUuids', QVariant(self.truncateUuids))
settings.setValue('config/ssgList', QVariant(ovs.json.to_string(self.ssgList)))
settings.sync()
self.emitUpdated()
def loadConfig(self):
settings = QtCore.QSettings()
jsonText = unicode(settings.value('config/hosts', QVariant('[]')).toString())
self.hosts = str_recursive(ovs.json.from_string(str(jsonText)))
self.logTraffic = settings.value('config/logTraffic', QVariant(False)).toBool()
self.truncateUuids = settings.value('config/truncateUuids', QVariant(False)).toBool()
jsonText = unicode(settings.value('config/ssgList', QVariant('[]')).toString())
self.ssgList = ovs.json.from_string(str(jsonText))
if len(self.ssgList) == 0:
self.ssgList = [
r'in_port0000',
r'in_port0001',
r'in_port0002',
r'in_port0003',
r'vlan65535',
r'type0800',
r'type0806',
r'proto0',
r'proto6',
r'proto17',
r'ff:ff:ff:ff:ff:ff',
r'!ff:ff:ff:ff:ff:ff',
r'0\.0\.0\.0',
r'!0\.0\.0\.0',
r'255\.255\.255\.255',
r'!255\.255\.255\.255',
r'never',
r'drop',
r'!never',
r'!drop',
r'(never|drop)',
r'!(never|drop)'
]
def emitUpdated(self):
self.emit(QtCore.SIGNAL("configUpdated()"))

View File

@@ -1,127 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
from OVELogger import *
from Ui_ConfigWindow import *
from OVEHostWindow import *
class OVEConfigWindow(QtGui.QDialog):
def __init__(self, app):
QtGui.QDialog.__init__(self)
self.app = app
self.ui = Ui_ConfigWindow()
self.ui.setupUi(self)
self.connect(self.ui.hostAddButton, QtCore.SIGNAL("clicked()"), self.xon_hostAddButton_clicked)
self.connect(self.ui.hostEditButton, QtCore.SIGNAL("clicked()"), self.xon_hostEditButton_clicked)
self.connect(self.ui.hostDeleteButton, QtCore.SIGNAL("clicked()"), self.xon_hostDeleteButton_clicked)
self.connect(self.ui.buttonBox, QtCore.SIGNAL("clicked(QAbstractButton *)"), self.xon_actionButton_Box_clicked)
self.connect(self.ui.hostList, QtCore.SIGNAL("currentItemChanged(QListWidgetItem *, QListWidgetItem *)"), self.xon_hostList_currentItemChanged)
self.connect(self.ui.logTrafficCheckBox, QtCore.SIGNAL("stateChanged(int)"), self.xon_logTrafficCheckBox_stateChanged)
self.connect(self.ui.truncateUuidsCheckBox, QtCore.SIGNAL("stateChanged(int)"), self.xon_truncateUuidsCheckBox_stateChanged)
self.readConfig()
self.updateWidgets()
def handleHostWindowRecord(self, record, isEdit):
if record['accepted'] and record['address'].strip() != '':
currentRow = self.ui.hostList.currentRow()
if isEdit:
self.configHosts[currentRow] = record
else:
self.configHosts.append(record)
self.updateWidgets()
def xon_hostAddButton_clicked(self):
hostWindow = OVEHostWindow(self)
hostWindow.exec_()
self.handleHostWindowRecord(hostWindow.record(), False)
def xon_hostEditButton_clicked(self):
if self.ui.hostList.currentItem() is None:
pass # OVELog('No item to edit')
else:
currentRow = self.ui.hostList.currentRow()
hostWindow = OVEHostWindow(self, self.configHosts[currentRow])
hostWindow.exec_()
self.handleHostWindowRecord(hostWindow.record(), True)
def xon_hostDeleteButton_clicked(self):
if self.ui.hostList.currentItem() is not None:
currentRow = self.ui.hostList.currentRow()
del self.configHosts[currentRow]
self.updateWidgets()
def xon_actionButton_Box_clicked(self, button):
role = self.ui.buttonBox.buttonRole(button)
if role == QtGui.QDialogButtonBox.AcceptRole:
self.writeConfig()
self.close()
elif role == QtGui.QDialogButtonBox.ApplyRole:
self.writeConfig()
elif role == QtGui.QDialogButtonBox.RejectRole:
if self.configChanged():
self.close()
else:
ret = QtGui.QMessageBox.warning(
self, "OVSDB Monitor",
"Changes not applied. Discard?",
QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Apply,
QtGui.QMessageBox.Discard)
if ret == QtGui.QMessageBox.Apply:
self.writeConfig()
if ret != QtGui.QMessageBox.Cancel:
self.close()
def xon_hostList_currentItemChanged(self, current, previous):
editable = (current is not None)
self.ui.hostEditButton.setEnabled(editable)
self.ui.hostDeleteButton.setEnabled(editable)
def xon_logTrafficCheckBox_stateChanged(self, value):
self.configLogTraffic = (value == Qt.Checked)
def xon_truncateUuidsCheckBox_stateChanged(self, value):
self.configTruncateUuids = (value == Qt.Checked)
def updateWidgets(self):
self.ui.hostList.clear()
for host in self.configHosts:
self.ui.hostList.addItem(host['address'])
self.ui.logTrafficCheckBox.setChecked(self.configLogTraffic)
self.ui.truncateUuidsCheckBox.setChecked(self.configTruncateUuids)
def configChanged(self):
return (
(self.configHosts == OVEConfig.Inst().hosts) and
(self.configLogTraffic == (OVEConfig.Inst().logTraffic))and
(self.configTruncateUuids == (OVEConfig.Inst().truncateUuids))
)
def readConfig(self):
self.configHosts = deepcopy(OVEConfig.Inst().hosts)
self.configLogTraffic = OVEConfig.Inst().logTraffic
self.configTruncateUuids = OVEConfig.Inst().truncateUuids
def writeConfig(self):
OVEConfig.Inst().hosts = deepcopy(self.configHosts)
OVEConfig.Inst().logTraffic = self.configLogTraffic
OVEConfig.Inst().truncateUuids = self.configTruncateUuids
OVEConfig.Inst().saveConfig()

View File

@@ -1,388 +0,0 @@
# Copyright (c) 2011 Nicira, Inc.
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
from OVELogger import *
import ovs.json
# This sequence installs the qt4reactor before twisted gets a chance to install its reactor
import qt4reactor
globalApp = QtGui.QApplication([])
qt4reactor.install()
try:
from twisted.conch.ssh import transport, userauth, connection, common, keys, channel
from twisted.internet import defer, protocol, reactor
from twisted.application import reactors
except Exception, e:
print('+++ Python Twisted Conch module is required\n')
raise
class OVEFetchUserAuth(userauth.SSHUserAuthClient):
def __init__(self, fetch, *params):
userauth.SSHUserAuthClient.__init__(self, *params)
self.fetch = fetch
self.authFails = 0
def getPassword(self):
return defer.succeed(self.fetch.config()['password'])
def ssh_USERAUTH_FAILURE(self, packet):
if self.authFails > 0: # We normally get one so ignore. Real failures send these repeatedly
OVELog('Authentication failure for '+self.fetch.config()['address'])
self.authFails += 1
userauth.SSHUserAuthClient.ssh_USERAUTH_FAILURE(self, packet)
class OVEFetchConnection(connection.SSHConnection, QtCore.QObject):
def __init__(self, fetch, *params):
connection.SSHConnection.__init__(self, *params)
QtCore.QObject.__init__(self)
self.fetch = fetch
self._channel = None
self._oldChannels = []
def serviceStarted(self):
self.emit(QtCore.SIGNAL('connectionService(QObject)'), self)
def serviceStopped(self):
self.emit(QtCore.SIGNAL('connectionService(QObject)'), None)
def execCommand(self, requester, ref, command, commandType):
if self._channel is not None:
# Don't delete old channels immediately in case they're e.g. going to time out with a failure
self._oldChannels.append(self._channel)
if len(self._oldChannels) > 90:
# For 30 second timeouts at 1 second refresh interval and three windows open on a single host, need 90 channels
del self._oldChannels[1]
self._channel = OVECommandChannel(self.fetch, requester, ref, command, commandType, 2**16, 2**15, self)
self.openChannel(self._channel)
def connectionLost(self, reason):
if self._channel is not None:
self._channel.connectionLost(reason)
class OVEFetchTransport(transport.SSHClientTransport, QtCore.QObject):
def __init__(self, fetch, *params):
# There is no __init__ method for this class
# transport.SSHClientTransport.__init__(self, *params)
QtCore.QObject.__init__(self)
self.fetch = fetch
self._connection = None
self.connect(self, QtCore.SIGNAL('channelFailure(QObject, int, QString, QString, QString)'), self.fetch.xon_channelFailure)
def verifyHostKey(self, hostKey, fingerprint):
return defer.succeed(1)
def connectionSecure(self):
self._connection = OVEFetchConnection(self.fetch)
QtCore.QObject.connect(self._connection, QtCore.SIGNAL('connectionService(QObject)'), self.fetch.xon_connectionService)
self.requestService(
OVEFetchUserAuth(self.fetch, self.fetch.config().get('username', 'root'),
self._connection))
def connectionLost(self, reason):
if self._connection is not None:
self._connection.connectionLost(reason)
class OVEFetchWrapper:
def __init__(self, contents):
self.contents = contents
class OVECommandChannel(channel.SSHChannel, QtCore.QObject):
name = 'session'
MSEC_TIMEOUT=10000
STATUS_CONNECTION_LOST = 100001
STATUS_TIMEOUT = 100002
END_MARKER='END-MARKER'
END_MARKER_RE=re.compile(r'^END-MARKER$', re.MULTILINE)
def __init__(self, fetch, requester, ref, command, commandType, *params):
channel.SSHChannel.__init__(self, *params)
QtCore.QObject.__init__(self)
self.fetch = fetch
self.requester = requester
self.ref = ref
self.command = command
self.commandType= commandType
self._data = ''
self._extData = ''
self._jsonValues = None
self._timerId = None
self._status = None
self.connect(self, QtCore.SIGNAL('channelData(QObject, int, QString)'), self.fetch.xon_channelData)
self.connect(self, QtCore.SIGNAL('channelExtData(QObject, int, QString)'), self.fetch.xon_channelExtData)
self.connect(self, QtCore.SIGNAL('channelSuccess(QObject, int, QString, QString, QVariant)'), self.fetch.xon_channelSuccess)
self.connect(self, QtCore.SIGNAL('channelFailure(QObject, int, QString, QString, QString)'), self.fetch.xon_channelFailure)
def openFailed(self, reason):
if self._timerId is not None:
self.killTimer(self._timerId)
self.emit(QtCore.SIGNAL('channelFailure(QObject, int, QString, QString, QString)'), self.requester, self.ref,
'Open failed:'+str(reason), '', '')
def channelOpen(self, ignoredData):
try:
nsCommand = common.NS(str(self.command))
self._timerId = self.startTimer(self.MSEC_TIMEOUT)
self.conn.sendRequest(self, 'exec', nsCommand, wantReply=1)
except Exception, e:
self.emit(QtCore.SIGNAL('channelFailure(QObject, int, QString, QString, QString)'), self.requester, self.ref,
'Open failed:'+str(e), self._data, self._extData)
def dataReceived(self, data):
self._data += data
if OVEConfig.Inst().logTraffic:
self.emit(QtCore.SIGNAL('channelData(QObject, int, QString)'), self.requester, self.ref, data)
self.testIfDone()
def extDataReceived(self, extData):
self._extData += extData
if OVEConfig.Inst().logTraffic:
self.emit(QtCore.SIGNAL('channelExtData(QObject, int, QString)'), self.requester, self.ref, extData)
def request_exit_status(self, data):
# We can get the exit status before the data, so delay calling sendResult until we get both
self._status = struct.unpack('>L', data)[0]
self.testIfDone()
def testIfDone(self):
if self._status is not None:
if self._status != 0:
self.sendResult() # Failed, so send what we have
elif len(self._data) > 0:
# Status == success and we have some data
if self.commandType == 'JSON':
try:
# Decode the JSON data, to confirm that we have all of the data
self._jsonValues = ovs.json.from_string(str(self._data)) # FIXME: Should handle unicode
self.sendResult()
except:
pass # Wait for more data
elif self.commandType == 'framed':
match = self.END_MARKER_RE.search(self._data)
if match:
self._data = self._data[:match.start()] # Remove end marker
self.sendResult()
else:
OVELog('Bad command type')
def sendResult(self):
if self._timerId is not None:
self.killTimer(self._timerId)
if self.commandType == 'JSON' and self._status == 0 and self._jsonValues is not None:
self.emit(QtCore.SIGNAL('channelSuccess(QObject, int, QString, QString, QVariant)'), self.requester, self.ref, self._data, self._extData, QVariant(OVEFetchWrapper(self._jsonValues)))
elif self.commandType != 'JSON' and self._status == 0:
self.emit(QtCore.SIGNAL('channelSuccess(QObject, int, QString, QString, QVariant)'), self.requester, self.ref, self._data, self._extData, QVariant(None))
else:
self.emit(QtCore.SIGNAL('channelFailure(QObject, int, QString, QString, QString)'), self.requester, self.ref, 'Remote command failed (rc='+str(self._status)+')', self._data, self._extData)
if self._status != self.STATUS_CONNECTION_LOST:
try:
self.loseConnection()
except Exception, e:
OVELog('OVECommandChannel.sendResult loseConnection error: '+str(e))
def connectionLost(self, reason):
self._extData += '+++ Connection lost'
self._status = self.STATUS_CONNECTION_LOST
self.sendResult()
def timerEvent(self, event):
if event.timerId() == self._timerId:
self._extData += '+++ Timeout'
self._status = self.STATUS_TIMEOUT
self.sendResult()
else:
QtCore.QObject.timerEvent(self, event)
class OVEFetchEvent(QtCore.QEvent):
TYPE = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
def __init__(self, ref, data):
QtCore.QEvent.__init__(self, self.TYPE)
self.ref = ref
self.data = data
class OVEFetchFailEvent(QtCore.QEvent):
TYPE = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
def __init__(self, ref, message):
QtCore.QEvent.__init__(self, self.TYPE)
self.ref = ref
self.message = str(message)
class OVEFetch(QtCore.QObject):
instances = {}
SEC_TIMEOUT = 10.0
def __init__(self, uuid):
QtCore.QObject.__init__(self)
self._hostUuid = uuid
self._config = None
self._transport = None
self._connection = None
self._commandQueue = []
self._timerRef = 0
self.refs = {}
self.messages = {}
self.values = {}
self.connect(OVEConfig.Inst(), QtCore.SIGNAL("configUpdated()"), self.xon_configUpdated)
@classmethod
def Inst(cls, uuid):
if uuid not in cls.instances:
cls.instances[uuid] = OVEFetch(uuid)
return cls.instances[uuid]
@classmethod
def startReactor(cls):
reactor.runReturn()
def xon_configUpdated(self):
self._config = None
self.resetTransport()
def xon_connectionService(self, connection):
self._connection = connection
if self._connection is not None:
OVELog('SSH connection to '+self.config()['address'] +' established')
for command in self._commandQueue:
# OVELog('Unqueueing '+str(command))
self.execCommand2(*command)
self._commandQueue = []
def xon_channelData(self, requester, ref, data):
if OVEConfig.Inst().logTraffic:
OVELog('Channel data received: '+str(data))
def xon_channelExtData(self, requester, ref, data):
if OVEConfig.Inst().logTraffic:
OVELog('+++ Channel extData (stderr) received: '+str(data))
def xon_channelFailure(self, requester, ref, message, data, extData):
if OVEConfig.Inst().logTraffic:
OVELog('+++ Channel failure: '+str(message))
OVELog("Closing SSH session due to failure")
errMessage = message
if len(data) > 0:
errMessage += '\n+++ Failed command output: '+data
if len(extData) > 0:
errMessage += '\n+++ Failed command output (stderr): '+extData
self.refs[requester] = ref # For PySide workaround
self.messages[requester] = errMessage # For PySide workaround
event = OVEFetchFailEvent(ref, errMessage)
QtCore.QCoreApplication.postEvent(requester, event)
self.resetTransport()
def xon_channelSuccess(self, requester, ref, data, extData, jsonValueVariant):
jsonValues = jsonValueVariant.toPyObject()
if OVEConfig.Inst().logTraffic:
OVELog('--- Channel success')
try:
if jsonValues is not None:
values = jsonValues.contents
else:
values = str(data)
self.refs[requester] = ref # For PySide workaround
self.values[requester] = values # For PySide workaround
event = OVEFetchEvent(ref, values)
QtCore.QCoreApplication.postEvent(requester, event)
except Exception, e:
message = ('+++ Failed to decode JSON reply: '+str(e))
if len(data) > 0: message += "\n++++++ Data (stdout): "+str(data)
if len(extData) > 0: message += '\n++++++ Error (stderr): '+str(extData)
self.refs[requester] = ref # For PySide workaround
self.messages[requester] = message # For PySide workaround
event = OVEFetchFailEvent(ref, message)
QtCore.QCoreApplication.postEvent(requester, event)
# Use for workaround only
def snoopRef(self, requester):
return self.refs.get(requester, None)
# Use for workaround only
def snoopValues(self, requester):
return self.values.get(requester, None)
# Use for workaround only
def snoopMessage(self, requester):
return self.messages.get(requester, None)
def config(self):
if self._config is None:
self._config = OVEConfig.Inst().hostFromUuid(self._hostUuid)
return self._config
def resetTransport(self):
if OVEConfig.Inst().logTraffic:
OVELog('Transport reset for '+self.config()['address'])
del self._connection
del self._transport
self._connection = None
self._transport = None
def transportErrback(self, failure, requester, ref, address):
self._timerRef += 1 # Prevent timeout handling
self.resetTransport()
message = 'Failure connecting to '+address+': '+failure.getErrorMessage()
self.refs[requester] = ref # For PySide workaround
self.messages[requester] = message # For PySide workaround
event = OVEFetchFailEvent(ref, message)
QtCore.QCoreApplication.postEvent(requester, event)
def transportTimeout(self, timerRef, requester, ref, address):
if self._timerRef == timerRef and self._transport is not None and self._connection is None:
message = 'Connection attempt to ' +address+' timed out'
self.refs[requester] = ref # For PySide workaround
self.messages[requester] = message # For PySide workaround
event = OVEFetchFailEvent(ref, message)
QtCore.QCoreApplication.postEvent(requester, event)
self.resetTransport()
def execCommand(self, requester, ref, command, commandType):
if OVEConfig.Inst().logTraffic:
hostName = (self.config() or {}).get('address', '<Address not set>')
OVELog(str(QtCore.QTime.currentTime().toString())+' '+hostName+': Executing '+command)
if self._transport is None:
self._connection = None
self._commandQueue.append((requester, ref, command, commandType))
config = self.config()
creator = protocol.ClientCreator(reactor, OVEFetchTransport, self)
self._transport = creator.connectTCP(config['address'], config.get('port', 22), timeout = self.SEC_TIMEOUT)
self._transport.addErrback(self.transportErrback, requester, ref, config['address'])
self._timerRef += 1
# Set this timer slightly longer than the twisted.conch timeout, as transportErrback can cancel
# the timeout and prevent double handling
# lambda timerRef = self._timerRef: takes a copy of self._timerRef
QtCore.QTimer.singleShot(int((1+self.SEC_TIMEOUT) * 1000), lambda timerRef = self._timerRef: self.transportTimeout(timerRef, requester, ref, config['address']))
else:
self.execCommand2(requester, ref, command, commandType)
def execCommand2(self, requester, ref, command, commandType):
if self._connection is None:
self._commandQueue.append((requester, ref, command, commandType))
else:
self._connection.execCommand(requester, ref, command, commandType)
def getTable(self, requester, tableName, ref = QtCore.QObject()):
command = '/usr/bin/ovsdb-client transact '+self.config()['connectTarget']+' \'["Open_vSwitch", {"op":"select","table":"'+tableName+'", "where":[]}]\''
self.execCommand(requester, ref, command, 'JSON')
def execCommandFramed(self, requester, ref, command):
self.execCommand(requester, ref, command + ' && echo ' + OVECommandChannel.END_MARKER, 'framed')

View File

@@ -1,327 +0,0 @@
# Copyright (c) 2011 Nicira, Inc.
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
from OVEFetch import *
from OVELogger import *
from OVEUtil import *
from OVECommonWindow import *
from Ui_FlowWindow import *
import re
class OVEFlowWindow(QtGui.QMainWindow, OVECommonWindow):
LOAD_KEY = 'FlowWindow/window'
COMMAND_OVS_DPCTL='/usr/bin/ovs-dpctl'
BASE_REF=200000
def __init__(self, app, loadIndex = None):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_FlowWindow()
self.dpNames = []
self.dpTables = []
self.currentOpIndex = None
self.resizeCount = []
self.ssgChecked = False
self.ssgText = ''
self.lastTime = None
self.lastByteCount = 0
OVECommonWindow.__init__(self, app, loadIndex)
self.updateSsgList()
self.updateDatapaths()
self.updateSsgState()
self.connect(self.ui.fetchPathsButton, QtCore.SIGNAL("clicked()"), self.xon_fetchPathsButton_clicked)
self.connect(self.ui.ssgSaveButton, QtCore.SIGNAL("clicked()"), self.xon_ssgSaveButton_clicked)
self.connect(self.ui.ssgDeleteButton, QtCore.SIGNAL("clicked()"), self.xon_ssgDeleteButton_clicked)
self.connect(self.ui.ssgComboBox, QtCore.SIGNAL("activated(int)"), self.xon_ssgComboBox_activated)
self.connect(self.ui.ssgComboBox, QtCore.SIGNAL("editTextChanged(QString)"), self.xon_ssgComboBox_editTextChanged)
self.connect(self.ui.ssgCheckBox, QtCore.SIGNAL("stateChanged(int)"), self.xon_ssgCheckBox_stateChanged)
def xon_fetchPathsButton_clicked(self):
self.updateDatapaths()
def xon_hostComboBox_currentIndexChanged(self, index):
OVECommonWindow.xon_hostComboBox_currentIndexChanged(self, index)
if (index >= 0):
self.updateDatapaths()
def xon_ssgSaveButton_clicked(self):
if self.ssgText not in OVEConfig.Inst().ssgList:
OVEConfig.Inst().ssgList.append(self.ssgText)
OVEConfig.Inst().saveConfig()
self.updateSsgList()
def updateSsgList(self):
currentSsgText = self.ssgText
self.ui.ssgComboBox.clear()
isFound = False
for i, ssgText in enumerate(OVEConfig.Inst().ssgList):
self.ui.ssgComboBox.addItem(ssgText)
if ssgText == currentSsgText:
# This is the currently selected item
self.ui.ssgComboBox.setCurrentIndex(i)
isFound = True
if not isFound:
self.ui.ssgComboBox.setCurrentIndex(-1)
self.ui.ssgComboBox.lineEdit().setText(currentSsgText)
def xon_ssgDeleteButton_clicked(self):
if self.ssgText in OVEConfig.Inst().ssgList:
OVEConfig.Inst().ssgList.remove(self.ssgText)
self.ssgText = ''
OVEConfig.Inst().saveConfig()
self.updateSsgList()
def xon_ssgComboBox_activated(self, index):
if (index >= 0):
itemData = self.ui.ssgComboBox.itemText(index)
self.ssgText = str(itemData)
self.updateTable()
def xon_ssgComboBox_editTextChanged(self, text):
self.ssgText = str(text)
self.statusBar().showMessage('Remote command is: '+self.updateCommand())
present = (self.ssgText in OVEConfig.Inst().ssgList)
self.ui.ssgDeleteButton.setEnabled(present)
self.ui.ssgSaveButton.setEnabled(not present)
def xon_ssgCheckBox_stateChanged(self, state):
self.ssgChecked = (state == Qt.Checked)
self.updateTable()
def xon_configUpdated(self):
OVECommonWindow.xon_configUpdated(self)
self.updateSsgList()
self.updateDatapaths()
def timerEvent(self, event):
OVECommonWindow.timerEvent(self, event)
def customEvent(self, event):
OVECommonWindow.customEvent(self, event)
def updateDatapaths(self):
if self.hostUuid == '':
self.statusBar().showMessage('No host selected')
else:
self.currentRef += 1
self.currentOp = 'dump-dps'
command = self.COMMAND_OVS_DPCTL+' dump-dps'
OVEFetch.Inst(self.hostUuid).execCommandFramed(self, self.currentRef, command)
def rebuildTables(self):
self.ui.tabWidget.clear() # Let the garbage collector delete the pages
self.dpTables = []
self.dpFlows = []
self.resizeCount = []
headings = OVEUtil.flowDecodeHeadings()
for dpName in self.dpNames:
pageWidget = QtGui.QWidget()
pageWidget.setObjectName(dpName+'_page')
gridLayout = QtGui.QGridLayout(pageWidget)
gridLayout.setObjectName(dpName+"_gridLayout")
table = QtGui.QTableWidget(pageWidget)
table.setObjectName(dpName+"_table")
table.setColumnCount(len(headings))
table.setRowCount(0)
gridLayout.addWidget(table, 0, 0, 1, 1)
self.dpTables.append(table)
self.ui.tabWidget.addTab(pageWidget, dpName)
self.dpFlows.append([])
self.resizeCount.append(0)
for i, heading in enumerate(headings):
table.setHorizontalHeaderItem(i, QtGui.QTableWidgetItem(heading))
table.setSortingEnabled(True)
table.sortItems(OVEUtil.getFlowColumn('source mac'))
table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
def updateSsgState(self):
self.ui.ssgCheckBox.setChecked(self.ssgChecked)
def updateCommand(self, overrideText = None):
command = self.COMMAND_OVS_DPCTL+' dump-flows '
if self.currentOpIndex is not None:
command += self.dpNames[self.currentOpIndex]
exp = None
if overrideText is not None:
exp = overrideText
elif self.ssgChecked:
exp = self.ssgText
if exp is not None:
opts='-E '
if exp.startswith('!'):
exp =exp[1:]
opts += '-v '
command += " | grep "+opts+"'"+exp+"' ; test ${PIPESTATUS[0]} -eq 0 "
return command
def updateTable(self):
if self.hostUuid == '':
self.statusBar().showMessage('No host selected')
self.setWindowTitle('OVS Flows')
elif len(self.dpNames) > 0:
config = OVEConfig.Inst().hostFromUuid(self.hostUuid)
self.setWindowTitle('OVS Flows - '+config.get('address', ''))
try:
self.setFetchSkip()
self.statusBar().showMessage('Fetching data...')
self.currentRef += 1
self.currentOp = 'dump-flows'
self.currentOpIndex = self.ui.tabWidget.currentIndex()
OVEFetch.Inst(self.hostUuid).execCommandFramed(self, self.currentRef, self.updateCommand())
except Exception, e:
message = 'Update failed: '+str(e)
OVELog(message)
self.statusBar().showMessage(message)
def writeCurrentTable(self):
index = self.ui.tabWidget.currentIndex()
actionsColumn = OVEUtil.getFlowColumn('actions')
usedColumn = OVEUtil.getFlowColumn('used')
srcMacColumn = OVEUtil.getFlowColumn('source mac')
destMacColumn = OVEUtil.getFlowColumn('destination mac')
srcIPColumn = OVEUtil.getFlowColumn('source ip')
destIPColumn = OVEUtil.getFlowColumn('destination ip')
inportColumn = OVEUtil.getFlowColumn('inport')
vlanColumn = OVEUtil.getFlowColumn('vlan')
bytesColumn = OVEUtil.getFlowColumn('bytes')
byteCount = 0
try:
table = self.dpTables[index]
table.setUpdatesEnabled(False)
table.setSortingEnabled(False)
try:
flows = self.dpFlows[index]
table.setRowCount(len(flows))
if len(flows) > 0:
table.setColumnCount(len(flows[0]))
for rowNum, flow in enumerate(flows):
inport = flow[inportColumn]
if flow[actionsColumn] == 'drop':
baseLum=172
else:
baseLum=239
background = QtGui.QColor(baseLum+16*(inport % 2), baseLum+8*(inport % 3), baseLum+4*(inport % 5))
if flow[usedColumn] == 'never':
colour = QtGui.QColor(112,112,112)
else:
colour = Qt.black
for colNum, data in enumerate(flow):
item = None
try:
item = table.takeItem(rowNum, colNum)
except:
pass
if item is None:
item = QtGui.QTableWidgetItem('')
if colNum == vlanColumn:
item.setBackground(QtGui.QColor(255-(10*data % 192), 255-((17*data) % 192), 255-((37*data) % 192)))
elif colNum == srcMacColumn or colNum == destMacColumn:
cols = [int(x, 16) for x in data.split(':')]
item.setBackground(QtGui.QColor(255-cols[2]*cols[3] % 192, 255-cols[3]*cols[4] % 192, 255-cols[4]*cols[5] % 192))
elif re.match(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', str(data)):
cols = [int(x) for x in data.split('.')]
item.setBackground(QtGui.QColor(255-cols[1]*cols[2] % 192, 255-cols[2]*cols[3] % 192, 255-cols[3]*cols[0] % 192))
else:
item.setBackground(background)
item.setForeground(colour)
if colNum == bytesColumn:
byteCount += int(data)
# PySide 0.2.3 fails to convert long ints to QVariants and logs 'long int too large to convert to int' errors
try:
item.setData(Qt.DisplayRole, QVariant(data))
item.setToolTip(str(data))
except Exception, e:
item.setText('Error: See tooltip')
item.setToolTip(str(e))
table.setItem(rowNum, colNum, item)
if self.resizeCount[index] < 2:
self.resizeCount[index] += 1
for i in range(0, table.columnCount()):
table.resizeColumnToContents(i)
finally:
table.setUpdatesEnabled(True)
table.setSortingEnabled(True)
message = 'Updated at '+str(QtCore.QTime.currentTime().toString())
if self.lastTime is not None:
timeDiff = time.time() - self.lastTime
byteDiff = byteCount - self.lastByteCount
bitRate = long(8 * byteDiff / timeDiff)
if abs(bitRate) < 10*2**20:
message += ' ('+str(bitRate/2**10)+' kbit/s)'
elif abs(bitRate) < 10*2**30:
message += ' ('+str(bitRate/2**20)+' Mbit/s)'
else:
message += ' ('+str(bitRate/2**30)+' Gbit/s)'
self.lastByteCount = byteCount
self.lastTime = time.time()
if table.rowCount() == 0:
message += ' - Table is empty'
self.statusBar().showMessage(message)
except Exception, e:
message = 'Table update failed: '+str(e)
OVELog(message)
self.statusBar().showMessage(message)
def handleFetchEvent(self, ref, values):
if self.currentOp == 'dump-dps':
self.dpNames =values.strip().split('\n')
self.rebuildTables()
self.updateTable()
elif self.currentOp == 'dump-flows':
self.dpFlows[self.currentOpIndex] = OVEUtil.decodeFlows(values)
self.writeCurrentTable()
def handleFetchFailEvent(self, ref, message):
self.statusBar().showMessage(message)
OVELog('Fetch ('+self.currentOp+') failed')
def customEvent(self, event):
OVECommonWindow.customEvent(self, event)
def saveSettings(self, index):
settings, key = OVECommonWindow.saveSettings(self, index)
settings.setValue(key+"/ssgText", QVariant(self.ssgText))
settings.setValue(key+"/ssgChecked", QVariant(self.ssgChecked))
def loadSettings(self, index):
settings, key = OVECommonWindow.loadSettings(self, index)
self.ssgText = str(settings.value(key+"/ssgText", QVariant('10\.80\.226\..*')).toString())
self.ssgChecked = settings.value(key+"/ssgChecked", QVariant(False)).toBool()
self.ssgRe = re.compile(self.ssgText)

View File

@@ -1,54 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVELogger import *
from Ui_HostWindow import *
class OVEHostWindow(QtGui.QDialog):
DEFAULT_CONNECT_TARGET = 'unix:/var/run/openvswitch/db.sock'
def __init__(self, parent, currentValues = None):
QtGui.QDialog.__init__(self, parent)
self.ui = Ui_HostWindow()
self.ui.setupUi(self)
self.resize(-1, -1)
self.connect(self.ui.buttonBox, QtCore.SIGNAL("clicked(QAbstractButton *)"), self.xon_actionButton_Box_clicked)
if currentValues is not None:
self.ui.hostAddressEdit.setText(currentValues['address'])
self.ui.hostPasswordEdit.setText(currentValues['password'])
self.ui.hostConnectTarget.setText(currentValues.get('connectTarget', self.DEFAULT_CONNECT_TARGET))
self.uuid = currentValues.get('uuid', str(uuid.uuid4()))
else:
self.ui.hostConnectTarget.setText(self.DEFAULT_CONNECT_TARGET)
self.uuid = str(uuid.uuid4())
self.accepted = None
def xon_actionButton_Box_clicked(self, button):
role = self.ui.buttonBox.buttonRole(button)
if role == QtGui.QDialogButtonBox.AcceptRole:
self.accepted = True
self.close()
elif role == QtGui.QDialogButtonBox.RejectRole:
self.accepted = False
self.close()
def record(self):
return {
'accepted' : self.accepted,
'uuid' : self.uuid,
'address' : str(self.ui.hostAddressEdit.text()),
'password' : str(self.ui.hostPasswordEdit.text()),
'connectTarget' : str(self.ui.hostConnectTarget.text())
}

View File

@@ -1,64 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVELogger import *
from Ui_LogWindow import *
class OVELogWindow(QtGui.QDialog):
LOAD_KEY = 'LogWindow/window'
def __init__(self, app):
QtGui.QDialog.__init__(self)
self.app = app
self.ui = Ui_LogWindow()
self.ui.setupUi(self)
if self.isLoadable():
self.loadSettings()
self.connect(OVELogger.Inst(), QtCore.SIGNAL("logUpdated()"), self.logUpdated)
self.connect(self.ui.buttonBox, QtCore.SIGNAL("clicked(QAbstractButton *)"), self.xon_actionButton_Box_clicked)
def xon_actionButton_Box_clicked(self, button):
role = self.ui.buttonBox.buttonRole(button)
if role == QtGui.QDialogButtonBox.ResetRole:
OVELogger.Inst().reset()
OVELog("Log reset")
def logUpdated(self):
self.ui.textBrowser.setText("\n".join(OVELogger.Inst().contents))
self.ui.textBrowser.moveCursor(QtGui.QTextCursor.End)
self.ui.textBrowser.ensureCursorVisible()
def saveSettings(self):
key = self.LOAD_KEY
settings = QtCore.QSettings()
settings.setValue(key+"/loadable", QVariant(True))
settings.setValue(key+"/pos", QVariant(self.pos()))
settings.setValue(key+"/size", QVariant(self.size()))
settings.setValue(key+"/visible", QVariant(self.isVisible()))
def loadSettings(self):
key = self.LOAD_KEY
settings = QtCore.QSettings()
pos = settings.value(key+"/pos", QVariant(QtCore.QPoint(200, 200))).toPoint()
size = settings.value(key+"/size", QVariant(QtCore.QSize(400, 400))).toSize()
visible = settings.value(key+"/visible", QVariant(True)).toBool()
self.resize(size)
self.move(pos)
self.setVisible(visible)
@classmethod
def isLoadable(cls):
key = cls.LOAD_KEY
settings = QtCore.QSettings()
return settings.value(key+"/loadable", QVariant(False)).toBool()

View File

@@ -1,45 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
class OVELogger(QtCore.QObject):
instance = None
def __init__(self):
QtCore.QObject.__init__(self)
self.contents = []
self.loggers = []
@classmethod
def Inst(cls):
if cls.instance is None:
cls.instance = OVELogger()
return cls.instance
def reset(self):
self.contents = []
self.update()
def logString(self, message):
self.contents += [str(message)]
if len(self.contents) > 500:
self.contents = ['+++ Log truncated', ''] + self.contents[50:]
self.update()
def update(self):
self.emit(QtCore.SIGNAL("logUpdated()"))
def OVELog(message):
OVELogger.Inst().logString(message)

View File

@@ -1,138 +0,0 @@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
from OVEFetch import *
from OVELogger import *
from OVEUtil import *
from OVECommonWindow import *
from Ui_MainWindow import *
class OVEMainWindow(QtGui.QMainWindow, OVECommonWindow):
LOAD_KEY = 'MainWindow/window'
BASE_REF=100000
def __init__(self, app, loadIndex = None):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
OVECommonWindow.__init__(self, app, loadIndex)
def xon_tabWidget_currentChanged(self, value):
self.deleteCurrentTable()
OVECommonWindow.xon_tabWidget_currentChanged(self, value)
def updateTable(self):
if self.hostUuid == '':
self.setWindowTitle('OVS Database')
self.deleteCurrentTable()
self.statusBar().showMessage('No host selected. Choose File->Preferences to add a host')
else:
config = OVEConfig.Inst().hostFromUuid(self.hostUuid)
self.setWindowTitle('OVS Database - '+config.get('address', ''))
self.invalidateCurrentTable('Fetching data...')
tabName = self.ui.tabWidget.currentWidget().objectName()
try:
self.setFetchSkip()
self.currentRef += 1
OVEFetch.Inst(self.hostUuid).getTable(self, tabName, self.currentRef)
except Exception, e:
OVELog("Error fetching data: "+str(e))
self.invalidateCurrentTable(str(e))
def timerEvent(self, event):
OVECommonWindow.timerEvent(self, event)
def customEvent(self, event):
OVECommonWindow.customEvent(self, event)
def handleFetchEvent(self, ref, values):
tabName = self.ui.tabWidget.currentWidget().objectName()
self.structToTable(getattr(self.ui, str(tabName)+'Table'), values)
def handleFetchFailEvent(self, ref, message):
self.invalidateCurrentTable(str(message))
def structToTable(self, table, values):
table.setUpdatesEnabled(False)
table.setSortingEnabled(False)
for result in values:
rowNum = 0
table.setRowCount(len(result['rows']))
for row in result['rows']:
table.setColumnCount(len(row))
colNum=0
for k in sorted(row.keys()):
v = row[k]
headerItem = QtGui.QTableWidgetItem(k)
table.setHorizontalHeaderItem(colNum, headerItem)
text = OVEUtil.paramToString(v)
item = QtGui.QTableWidgetItem(text)
longText = OVEUtil.paramToLongString(v)
item.setToolTip(longText)
table.setItem(rowNum, colNum, item)
colNum+=1
rowNum+=1
for i in range(0, table.columnCount()):
table.resizeColumnToContents(i)
for i in range(0, table.rowCount()):
table.resizeRowToContents(i)
# table.setSortingEnabled(True)
table.setUpdatesEnabled(True)
message = 'Updated at '+str(QtCore.QTime.currentTime().toString())
if table.rowCount() == 0:
message += ' - Table is empty'
self.statusBar().showMessage(message)
def invalidateCurrentTable(self, message):
tabName = self.ui.tabWidget.currentWidget().objectName()
self.invalidateTable(getattr(self.ui, str(tabName)+'Table'), message)
def invalidateTable(self, table, message):
table.setUpdatesEnabled(False)
table.setSortingEnabled(False)
for rowNum in range(0, table.rowCount()):
for colNum in range(0, table.columnCount()):
item = table.takeItem(rowNum, colNum)
if item is not None:
item.setForeground(Qt.darkGray)
table.setItem(rowNum, colNum, item)
self.statusBar().showMessage(message)
# table.setSortingEnabled(True)
table.setUpdatesEnabled(True)
def deleteCurrentTable(self):
tabName = self.ui.tabWidget.currentWidget().objectName()
self.deleteTable(getattr(self.ui, str(tabName)+'Table'))
def deleteTable(self, table):
table.clear()
table.setRowCount(0)
table.setColumnCount(0)
def saveSettings(self, index):
settings = OVECommonWindow.saveSettings(self, index)
def loadSettings(self, index):
settings = OVECommonWindow.loadSettings(self, index)

View File

@@ -1,42 +0,0 @@
# Copyright (c) 2011 Nicira, Inc.
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os, re, struct, sys, time, types, uuid
from copy import deepcopy
from pprint import pprint
# Set globalForcePySide to True to use PySide instead of PyQt if both are installed
globalForcePySide = False
try:
import ovs.json
except Exception, e:
print('+++ OVS JSON module is required\n')
raise
try:
if globalForcePySide:
print('Forcing use of PySide')
raise Exception()
from PyQt4.QtCore import Qt, QVariant
from PyQt4 import QtCore, QtGui
except:
try:
from PySide.QtCore import Qt, QVariant
from PySide import QtCore, QtGui
except Exception, e:
print('+++ This application requires either PyQt4 or PySide\n')
raise

View File

@@ -1,135 +0,0 @@
# Copyright (c) 2011 Nicira, Inc.
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from OVEStandard import *
from OVEConfig import *
import re
class OVEUtil:
UUID_RE = re.compile(r'([a-f0-9]{8}-[a-f0-9]{2})[a-f0-9]{2}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}')
@classmethod
def paramToLongString(cls, param):
if isinstance(param, (types.ListType, types.TupleType)) and len(param) > 1:
text = str(param[1])
else:
text = str(param)
return text.replace(', ', ',\n')
@classmethod
def paramToString(cls, param):
if isinstance(param, (types.ListType, types.TupleType)) and len(param) > 1:
text = str(param[1])
else:
text = str(param)
if OVEConfig.Inst().truncateUuids:
text = cls.UUID_RE.sub('\\1...', text)
return text.replace(', ', ',\n')
@classmethod
def flowDecodeHeadings(self):
return [
'Type',
'Proto',
'Inport',
'VLAN',
'Source MAC',
'Destination MAC',
'Source IP',
'Destination IP',
'Src port',
'Dest port',
'Packet count',
'Bytes',
'Used',
'Tos',
'PCP',
'Tunnel',
'Actions',
]
@classmethod
def getFlowColumn(cls, name):
lowerName = name.lower()
for i, columnName in enumerate(cls.flowDecodeHeadings()):
if lowerName == columnName.lower():
return i
return None
ETHERTYPE_TRANS = {
'05ff':'ESX probe',
'0800':'IP',
'0806':'ARP',
'86dd':'IPv6',
'88cc':'LLDP'
}
ETHERPROTO_TRANS = {
'1':'ICMP',
'6':'TCP',
'17':'UDP'
}
# Parsing of ovs-dpctl dump-flows output should be localised in this method and flowDecodeHeadings
@classmethod
def decodeFlows(cls, srcLines):
retVal = []
for line in srcLines.split('\n'):
if line != '':
fields = {}
for name, val in re.findall(r'([a-zA-Z0-9_+]+)\(([^)]+)\)', line):
if '=' in val:
for setting in val.split(','):
k,v = setting.split('=')
fields['%s.%s' % (name, k)] = v
else:
fields[name] = val
for setting in re.split(', ', line)[1:]:
if ':' in setting:
k,v = setting.split(':')
fields[k] = v
tun_id = fields.get('tun_id', '')
in_port = int(fields.get('in_port', 0))
eth_src = fields.get('eth.src', '')
eth_dst = fields.get('eth.dst', '')
vlan_vid = int(fields.get('vlan.vid', 0))
vlan_pcp = int(fields.get('vlan.pcp', 0))
eth_type = fields.get('eth_type', '')
ip_src = fields.get('ipv4.src', fields.get('ipv6.src', ''))
ip_dst = fields.get('ipv4.dst', fields.get('ipv6.dst', ''))
ip_proto = fields.get('ipv4.proto', fields.get('ipv6.proto', ''))
ip_tos = fields.get('ipv4.tos', fields.get('ipv6.tos', ''))
tp_src = fields.get('tcp.src', fields.get('udp.src', fields.get('arp.sip', fields.get('icmp.type', fields.get('icmpv6.type', '')))))
tp_dst = fields.get('tcp.dst', fields.get('udp.dst', fields.get('arp.tip', fields.get('icmp.code', fields.get('icmpv6.code', '')))))
packets = fields.get('packets', '')
bytes = fields.get('bytes', '')
actions = fields.get('actions', '')
used = fields.get('used', '')
# Order below needs to match that in flowDecodeHeadings
retVal.append((eth_type, ip_proto, in_port, vlan_vid, eth_src, eth_dst, ip_src, ip_dst, tp_src, tp_dst, packets, bytes, used, ip_tos, vlan_pcp, tun_id, actions))
return retVal
COLOURS = [Qt.black, Qt.darkBlue, Qt.darkRed, Qt.darkGreen, Qt.darkMagenta, Qt.darkCyan, Qt.darkGray, Qt.darkYellow, Qt.blue, Qt.gray, Qt.magenta, Qt.red]
@classmethod
def intToColour(cls, value):
return cls.COLOURS[value % len(cls.COLOURS)]

View File

@@ -1,106 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ConfigWindow.ui'
#
# Created: Fri May 7 17:20:33 2010
# by: PyQt4 UI code generator 4.4.2
#
# WARNING! All changes made in this file will be lost!
try:
from OVEStandard import globalForcePySide
if globalForcePySide: raise Exception()
from PyQt4 import QtCore, QtGui
except:
from PySide import QtCore, QtGui
class Ui_ConfigWindow(object):
def setupUi(self, ConfigWindow):
ConfigWindow.setObjectName("ConfigWindow")
ConfigWindow.resize(386,303)
ConfigWindow.setFocusPolicy(QtCore.Qt.TabFocus)
self.gridLayout = QtGui.QGridLayout(ConfigWindow)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget = QtGui.QTabWidget(ConfigWindow)
self.tabWidget.setObjectName("tabWidget")
self.hosts = QtGui.QWidget()
self.hosts.setObjectName("hosts")
self.layoutWidget = QtGui.QWidget(self.hosts)
self.layoutWidget.setGeometry(QtCore.QRect(10,10,341,194))
self.layoutWidget.setObjectName("layoutWidget")
self.horizontalLayout_2 = QtGui.QHBoxLayout(self.layoutWidget)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.hostList = QtGui.QListWidget(self.layoutWidget)
self.hostList.setObjectName("hostList")
self.horizontalLayout_2.addWidget(self.hostList)
self.verticalLayout_2 = QtGui.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.hostAddButton = QtGui.QPushButton(self.layoutWidget)
self.hostAddButton.setObjectName("hostAddButton")
self.verticalLayout_2.addWidget(self.hostAddButton)
self.hostEditButton = QtGui.QPushButton(self.layoutWidget)
self.hostEditButton.setObjectName("hostEditButton")
self.verticalLayout_2.addWidget(self.hostEditButton)
self.hostDeleteButton = QtGui.QPushButton(self.layoutWidget)
self.hostDeleteButton.setObjectName("hostDeleteButton")
self.verticalLayout_2.addWidget(self.hostDeleteButton)
spacerItem = QtGui.QSpacerItem(20,40,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem)
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
self.tabWidget.addTab(self.hosts,"")
self.logging = QtGui.QWidget()
self.logging.setObjectName("logging")
self.gridLayout_2 = QtGui.QGridLayout(self.logging)
self.gridLayout_2.setObjectName("gridLayout_2")
self.logTrafficCheckBox = QtGui.QCheckBox(self.logging)
self.logTrafficCheckBox.setObjectName("logTrafficCheckBox")
self.gridLayout_2.addWidget(self.logTrafficCheckBox,0,0,1,1)
spacerItem1 = QtGui.QSpacerItem(20,164,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem1,1,0,1,1)
self.tabWidget.addTab(self.logging,"")
self.view = QtGui.QWidget()
self.view.setObjectName("view")
self.verticalLayout_3 = QtGui.QVBoxLayout(self.view)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.truncateUuidsCheckBox = QtGui.QCheckBox(self.view)
self.truncateUuidsCheckBox.setObjectName("truncateUuidsCheckBox")
self.verticalLayout_3.addWidget(self.truncateUuidsCheckBox)
spacerItem2 = QtGui.QSpacerItem(20,164,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
self.verticalLayout_3.addItem(spacerItem2)
self.tabWidget.addTab(self.view,"")
self.verticalLayout.addWidget(self.tabWidget)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem3 = QtGui.QSpacerItem(40,20,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem3)
self.buttonBox = QtGui.QDialogButtonBox(ConfigWindow)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Apply|QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.horizontalLayout.addWidget(self.buttonBox)
self.verticalLayout.addLayout(self.horizontalLayout)
self.gridLayout.addLayout(self.verticalLayout,0,0,1,1)
self.retranslateUi(ConfigWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(ConfigWindow)
ConfigWindow.setTabOrder(self.hostList,self.hostAddButton)
ConfigWindow.setTabOrder(self.hostAddButton,self.hostEditButton)
ConfigWindow.setTabOrder(self.hostEditButton,self.hostDeleteButton)
ConfigWindow.setTabOrder(self.hostDeleteButton,self.buttonBox)
ConfigWindow.setTabOrder(self.buttonBox,self.tabWidget)
def retranslateUi(self, ConfigWindow):
ConfigWindow.setWindowTitle(QtGui.QApplication.translate("ConfigWindow", "OVSDB Monitor Configuration", None, QtGui.QApplication.UnicodeUTF8))
self.hostAddButton.setText(QtGui.QApplication.translate("ConfigWindow", "Add", None, QtGui.QApplication.UnicodeUTF8))
self.hostEditButton.setText(QtGui.QApplication.translate("ConfigWindow", "Edit", None, QtGui.QApplication.UnicodeUTF8))
self.hostDeleteButton.setText(QtGui.QApplication.translate("ConfigWindow", "Delete", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.hosts), QtGui.QApplication.translate("ConfigWindow", "Hosts", None, QtGui.QApplication.UnicodeUTF8))
self.logTrafficCheckBox.setToolTip(QtGui.QApplication.translate("ConfigWindow", "Whether to log traffic exchanges in the log window", None, QtGui.QApplication.UnicodeUTF8))
self.logTrafficCheckBox.setText(QtGui.QApplication.translate("ConfigWindow", "Log traffic", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.logging), QtGui.QApplication.translate("ConfigWindow", "Logging", None, QtGui.QApplication.UnicodeUTF8))
self.truncateUuidsCheckBox.setToolTip(QtGui.QApplication.translate("ConfigWindow", "Replaces UUIDs with a shorter string of the first few characters. The tooltip still contains the full value", None, QtGui.QApplication.UnicodeUTF8))
self.truncateUuidsCheckBox.setText(QtGui.QApplication.translate("ConfigWindow", "Truncate UUIDs", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.view), QtGui.QApplication.translate("ConfigWindow", "View", None, QtGui.QApplication.UnicodeUTF8))

View File

@@ -1,136 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'FlowWindow.ui'
#
# Created: Fri May 7 17:20:33 2010
# by: PyQt4 UI code generator 4.4.2
#
# WARNING! All changes made in this file will be lost!
try:
from OVEStandard import globalForcePySide
if globalForcePySide: raise Exception()
from PyQt4 import QtCore, QtGui
except:
from PySide import QtCore, QtGui
class Ui_FlowWindow(object):
def setupUi(self, FlowWindow):
FlowWindow.setObjectName("FlowWindow")
FlowWindow.resize(800,600)
self.centralwidget = QtGui.QWidget(FlowWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.tabWidget = QtGui.QTabWidget(self.centralwidget)
self.tabWidget.setObjectName("tabWidget")
self.unset = QtGui.QWidget()
self.unset.setObjectName("unset")
self.gridLayout_10 = QtGui.QGridLayout(self.unset)
self.gridLayout_10.setObjectName("gridLayout_10")
self.tabWidget.addTab(self.unset,"")
self.gridLayout.addWidget(self.tabWidget,0,0,1,1)
self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.ssgCheckBox = QtGui.QCheckBox(self.centralwidget)
self.ssgCheckBox.setObjectName("ssgCheckBox")
self.horizontalLayout_2.addWidget(self.ssgCheckBox)
self.ssgComboBox = QtGui.QComboBox(self.centralwidget)
self.ssgComboBox.setEditable(True)
self.ssgComboBox.setMaxVisibleItems(20)
self.ssgComboBox.setInsertPolicy(QtGui.QComboBox.NoInsert)
self.ssgComboBox.setMinimumContentsLength(32)
self.ssgComboBox.setObjectName("ssgComboBox")
self.horizontalLayout_2.addWidget(self.ssgComboBox)
self.ssgSaveButton = QtGui.QPushButton(self.centralwidget)
self.ssgSaveButton.setObjectName("ssgSaveButton")
self.horizontalLayout_2.addWidget(self.ssgSaveButton)
self.ssgDeleteButton = QtGui.QPushButton(self.centralwidget)
self.ssgDeleteButton.setObjectName("ssgDeleteButton")
self.horizontalLayout_2.addWidget(self.ssgDeleteButton)
spacerItem = QtGui.QSpacerItem(40,20,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Minimum)
self.horizontalLayout_2.addItem(spacerItem)
self.gridLayout.addLayout(self.horizontalLayout_2,1,0,1,1)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.hostLabel = QtGui.QLabel(self.centralwidget)
self.hostLabel.setObjectName("hostLabel")
self.horizontalLayout.addWidget(self.hostLabel)
self.hostComboBox = QtGui.QComboBox(self.centralwidget)
self.hostComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
self.hostComboBox.setObjectName("hostComboBox")
self.horizontalLayout.addWidget(self.hostComboBox)
self.intervalCheckBox = QtGui.QCheckBox(self.centralwidget)
self.intervalCheckBox.setObjectName("intervalCheckBox")
self.horizontalLayout.addWidget(self.intervalCheckBox)
self.intervalSpinBox = QtGui.QSpinBox(self.centralwidget)
self.intervalSpinBox.setMinimum(1)
self.intervalSpinBox.setMaximum(1000000)
self.intervalSpinBox.setObjectName("intervalSpinBox")
self.horizontalLayout.addWidget(self.intervalSpinBox)
spacerItem1 = QtGui.QSpacerItem(40,20,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.fetchPathsButton = QtGui.QPushButton(self.centralwidget)
self.fetchPathsButton.setObjectName("fetchPathsButton")
self.horizontalLayout.addWidget(self.fetchPathsButton)
self.fetchButton = QtGui.QPushButton(self.centralwidget)
self.fetchButton.setObjectName("fetchButton")
self.horizontalLayout.addWidget(self.fetchButton)
self.gridLayout.addLayout(self.horizontalLayout,3,0,1,1)
self.line = QtGui.QFrame(self.centralwidget)
self.line.setFrameShape(QtGui.QFrame.HLine)
self.line.setFrameShadow(QtGui.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout.addWidget(self.line,2,0,1,1)
FlowWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(FlowWindow)
self.menubar.setGeometry(QtCore.QRect(0,0,800,28))
self.menubar.setObjectName("menubar")
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
FlowWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(FlowWindow)
self.statusbar.setObjectName("statusbar")
FlowWindow.setStatusBar(self.statusbar)
self.actionShow_Log = QtGui.QAction(FlowWindow)
self.actionShow_Log.setObjectName("actionShow_Log")
self.actionNew_DB_Window = QtGui.QAction(FlowWindow)
self.actionNew_DB_Window.setObjectName("actionNew_DB_Window")
self.actionPreferences = QtGui.QAction(FlowWindow)
self.actionPreferences.setObjectName("actionPreferences")
self.actionQuit = QtGui.QAction(FlowWindow)
self.actionQuit.setObjectName("actionQuit")
self.actionNew_Flow_Window = QtGui.QAction(FlowWindow)
self.actionNew_Flow_Window.setObjectName("actionNew_Flow_Window")
self.menuFile.addAction(self.actionNew_DB_Window)
self.menuFile.addAction(self.actionNew_Flow_Window)
self.menuFile.addAction(self.actionShow_Log)
self.menuFile.addAction(self.actionPreferences)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionQuit)
self.menubar.addAction(self.menuFile.menuAction())
self.hostLabel.setBuddy(self.hostComboBox)
self.retranslateUi(FlowWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(FlowWindow)
def retranslateUi(self, FlowWindow):
FlowWindow.setWindowTitle(QtGui.QApplication.translate("FlowWindow", "OVSDB Monitor", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.unset), QtGui.QApplication.translate("FlowWindow", "Awaiting update...", None, QtGui.QApplication.UnicodeUTF8))
self.ssgCheckBox.setText(QtGui.QApplication.translate("FlowWindow", "Server-side grep", None, QtGui.QApplication.UnicodeUTF8))
self.ssgSaveButton.setText(QtGui.QApplication.translate("FlowWindow", "Save", None, QtGui.QApplication.UnicodeUTF8))
self.ssgDeleteButton.setText(QtGui.QApplication.translate("FlowWindow", "Delete", None, QtGui.QApplication.UnicodeUTF8))
self.hostLabel.setText(QtGui.QApplication.translate("FlowWindow", "Host", None, QtGui.QApplication.UnicodeUTF8))
self.intervalCheckBox.setText(QtGui.QApplication.translate("FlowWindow", "Auto-refetch every", None, QtGui.QApplication.UnicodeUTF8))
self.intervalSpinBox.setSuffix(QtGui.QApplication.translate("FlowWindow", "s", None, QtGui.QApplication.UnicodeUTF8))
self.fetchPathsButton.setToolTip(QtGui.QApplication.translate("FlowWindow", "Refetches the datapath names and rebuilds the window tabs to reflect them. Use when the network has been reconfigured, e.g. a bond has been created", None, QtGui.QApplication.UnicodeUTF8))
self.fetchPathsButton.setText(QtGui.QApplication.translate("FlowWindow", "Refetch Datapath List", None, QtGui.QApplication.UnicodeUTF8))
self.fetchButton.setText(QtGui.QApplication.translate("FlowWindow", "Refetch", None, QtGui.QApplication.UnicodeUTF8))
self.menuFile.setTitle(QtGui.QApplication.translate("FlowWindow", "File", None, QtGui.QApplication.UnicodeUTF8))
self.actionShow_Log.setText(QtGui.QApplication.translate("FlowWindow", "Show Log", None, QtGui.QApplication.UnicodeUTF8))
self.actionNew_DB_Window.setText(QtGui.QApplication.translate("FlowWindow", "New DB Window", None, QtGui.QApplication.UnicodeUTF8))
self.actionPreferences.setText(QtGui.QApplication.translate("FlowWindow", "Preferences", None, QtGui.QApplication.UnicodeUTF8))
self.actionQuit.setText(QtGui.QApplication.translate("FlowWindow", "Quit", None, QtGui.QApplication.UnicodeUTF8))
self.actionNew_Flow_Window.setText(QtGui.QApplication.translate("FlowWindow", "New Flow Window", None, QtGui.QApplication.UnicodeUTF8))

View File

@@ -1,75 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'HostWindow.ui'
#
# Created: Fri May 7 17:20:33 2010
# by: PyQt4 UI code generator 4.4.2
#
# WARNING! All changes made in this file will be lost!
try:
from OVEStandard import globalForcePySide
if globalForcePySide: raise Exception()
from PyQt4 import QtCore, QtGui
except:
from PySide import QtCore, QtGui
class Ui_HostWindow(object):
def setupUi(self, HostWindow):
HostWindow.setObjectName("HostWindow")
HostWindow.setWindowModality(QtCore.Qt.WindowModal)
HostWindow.resize(400,300)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(HostWindow.sizePolicy().hasHeightForWidth())
HostWindow.setSizePolicy(sizePolicy)
self.gridLayout_2 = QtGui.QGridLayout(HostWindow)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gridLayout = QtGui.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label = QtGui.QLabel(HostWindow)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label,0,0,1,1)
self.hostAddressEdit = QtGui.QLineEdit(HostWindow)
self.hostAddressEdit.setMinimumSize(QtCore.QSize(256,0))
self.hostAddressEdit.setObjectName("hostAddressEdit")
self.gridLayout.addWidget(self.hostAddressEdit,0,1,1,1)
self.label_2 = QtGui.QLabel(HostWindow)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2,1,0,1,1)
self.hostPasswordEdit = QtGui.QLineEdit(HostWindow)
self.hostPasswordEdit.setMinimumSize(QtCore.QSize(256,0))
self.hostPasswordEdit.setEchoMode(QtGui.QLineEdit.Password)
self.hostPasswordEdit.setObjectName("hostPasswordEdit")
self.gridLayout.addWidget(self.hostPasswordEdit,1,1,1,1)
self.label_3 = QtGui.QLabel(HostWindow)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3,2,0,1,1)
self.hostConnectTarget = QtGui.QLineEdit(HostWindow)
self.hostConnectTarget.setMinimumSize(QtCore.QSize(256,0))
self.hostConnectTarget.setObjectName("hostConnectTarget")
self.gridLayout.addWidget(self.hostConnectTarget,2,1,1,1)
self.gridLayout_2.addLayout(self.gridLayout,0,0,1,1)
self.buttonBox = QtGui.QDialogButtonBox(HostWindow)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout_2.addWidget(self.buttonBox,1,0,1,1)
self.label.setBuddy(self.hostAddressEdit)
self.label_2.setBuddy(self.hostPasswordEdit)
self.label_3.setBuddy(self.hostConnectTarget)
self.retranslateUi(HostWindow)
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("accepted()"),HostWindow.accept)
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("rejected()"),HostWindow.reject)
QtCore.QMetaObject.connectSlotsByName(HostWindow)
HostWindow.setTabOrder(self.hostAddressEdit,self.hostPasswordEdit)
HostWindow.setTabOrder(self.hostPasswordEdit,self.buttonBox)
def retranslateUi(self, HostWindow):
HostWindow.setWindowTitle(QtGui.QApplication.translate("HostWindow", "Host Properties", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("HostWindow", "Host name or IP", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("HostWindow", "SSH Password", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("HostWindow", "Connect target", None, QtGui.QApplication.UnicodeUTF8))

View File

@@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'LogWindow.ui'
#
# Created: Fri May 7 17:20:33 2010
# by: PyQt4 UI code generator 4.4.2
#
# WARNING! All changes made in this file will be lost!
try:
from OVEStandard import globalForcePySide
if globalForcePySide: raise Exception()
from PyQt4 import QtCore, QtGui
except:
from PySide import QtCore, QtGui
class Ui_LogWindow(object):
def setupUi(self, LogWindow):
LogWindow.setObjectName("LogWindow")
LogWindow.resize(735,558)
self.gridLayout = QtGui.QGridLayout(LogWindow)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.textBrowser = QtGui.QTextBrowser(LogWindow)
self.textBrowser.setObjectName("textBrowser")
self.verticalLayout.addWidget(self.textBrowser)
self.buttonBox = QtGui.QDialogButtonBox(LogWindow)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Close|QtGui.QDialogButtonBox.Reset)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.gridLayout.addLayout(self.verticalLayout,0,0,1,1)
self.retranslateUi(LogWindow)
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("accepted()"),LogWindow.accept)
QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("rejected()"),LogWindow.reject)
QtCore.QMetaObject.connectSlotsByName(LogWindow)
def retranslateUi(self, LogWindow):
LogWindow.setWindowTitle(QtGui.QApplication.translate("LogWindow", "OVSDB Monitor Log", None, QtGui.QApplication.UnicodeUTF8))

View File

@@ -1,222 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '../ovsdb/ovsdbmonitor/MainWindow.ui'
#
# Created: Mon May 17 16:23:47 2010
# by: PyQt4 UI code generator 4.7.3
#
# WARNING! All changes made in this file will be lost!
try:
from OVEStandard import globalForcePySide
if globalForcePySide:
raise Exception()
from PyQt4 import QtCore, QtGui
except:
from PySide import QtCore, QtGui
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtGui.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget = QtGui.QTabWidget(self.centralwidget)
self.tabWidget.setObjectName("tabWidget")
self.Bridge = QtGui.QWidget()
self.Bridge.setObjectName("Bridge")
self.gridLayout_2 = QtGui.QGridLayout(self.Bridge)
self.gridLayout_2.setObjectName("gridLayout_2")
self.BridgeTable = QtGui.QTableWidget(self.Bridge)
self.BridgeTable.setObjectName("BridgeTable")
self.BridgeTable.setColumnCount(0)
self.BridgeTable.setRowCount(0)
self.gridLayout_2.addWidget(self.BridgeTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Bridge, "")
self.Controller = QtGui.QWidget()
self.Controller.setObjectName("Controller")
self.gridLayout_3 = QtGui.QGridLayout(self.Controller)
self.gridLayout_3.setObjectName("gridLayout_3")
self.ControllerTable = QtGui.QTableWidget(self.Controller)
self.ControllerTable.setObjectName("ControllerTable")
self.ControllerTable.setColumnCount(0)
self.ControllerTable.setRowCount(0)
self.gridLayout_3.addWidget(self.ControllerTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Controller, "")
self.Interface = QtGui.QWidget()
self.Interface.setObjectName("Interface")
self.gridLayout_4 = QtGui.QGridLayout(self.Interface)
self.gridLayout_4.setObjectName("gridLayout_4")
self.InterfaceTable = QtGui.QTableWidget(self.Interface)
self.InterfaceTable.setObjectName("InterfaceTable")
self.InterfaceTable.setColumnCount(0)
self.InterfaceTable.setRowCount(0)
self.gridLayout_4.addWidget(self.InterfaceTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Interface, "")
self.Mirror = QtGui.QWidget()
self.Mirror.setObjectName("Mirror")
self.gridLayout_5 = QtGui.QGridLayout(self.Mirror)
self.gridLayout_5.setObjectName("gridLayout_5")
self.MirrorTable = QtGui.QTableWidget(self.Mirror)
self.MirrorTable.setObjectName("MirrorTable")
self.MirrorTable.setColumnCount(0)
self.MirrorTable.setRowCount(0)
self.gridLayout_5.addWidget(self.MirrorTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Mirror, "")
self.NetFlow = QtGui.QWidget()
self.NetFlow.setObjectName("NetFlow")
self.gridLayout_6 = QtGui.QGridLayout(self.NetFlow)
self.gridLayout_6.setObjectName("gridLayout_6")
self.NetFlowTable = QtGui.QTableWidget(self.NetFlow)
self.NetFlowTable.setObjectName("NetFlowTable")
self.NetFlowTable.setColumnCount(0)
self.NetFlowTable.setRowCount(0)
self.gridLayout_6.addWidget(self.NetFlowTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.NetFlow, "")
self.Open_vSwitch = QtGui.QWidget()
self.Open_vSwitch.setObjectName("Open_vSwitch")
self.gridLayout_7 = QtGui.QGridLayout(self.Open_vSwitch)
self.gridLayout_7.setObjectName("gridLayout_7")
self.Open_vSwitchTable = QtGui.QTableWidget(self.Open_vSwitch)
self.Open_vSwitchTable.setObjectName("Open_vSwitchTable")
self.Open_vSwitchTable.setColumnCount(0)
self.Open_vSwitchTable.setRowCount(0)
self.gridLayout_7.addWidget(self.Open_vSwitchTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Open_vSwitch, "")
self.Port = QtGui.QWidget()
self.Port.setObjectName("Port")
self.gridLayout_8 = QtGui.QGridLayout(self.Port)
self.gridLayout_8.setObjectName("gridLayout_8")
self.PortTable = QtGui.QTableWidget(self.Port)
self.PortTable.setObjectName("PortTable")
self.PortTable.setColumnCount(0)
self.PortTable.setRowCount(0)
self.gridLayout_8.addWidget(self.PortTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Port, "")
self.QoS = QtGui.QWidget()
self.QoS.setObjectName("QoS")
self.gridLayout_10 = QtGui.QGridLayout(self.QoS)
self.gridLayout_10.setObjectName("gridLayout_10")
self.QoSTable = QtGui.QTableWidget(self.QoS)
self.QoSTable.setObjectName("QoSTable")
self.QoSTable.setColumnCount(0)
self.QoSTable.setRowCount(0)
self.gridLayout_10.addWidget(self.QoSTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.QoS, "")
self.Queue = QtGui.QWidget()
self.Queue.setObjectName("Queue")
self.gridLayout_11 = QtGui.QGridLayout(self.Queue)
self.gridLayout_11.setObjectName("gridLayout_11")
self.QueueTable = QtGui.QTableWidget(self.Queue)
self.QueueTable.setObjectName("QueueTable")
self.QueueTable.setColumnCount(0)
self.QueueTable.setRowCount(0)
self.gridLayout_11.addWidget(self.QueueTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.Queue, "")
self.sFlow = QtGui.QWidget()
self.sFlow.setObjectName("sFlow")
self.gridLayout_9 = QtGui.QGridLayout(self.sFlow)
self.gridLayout_9.setObjectName("gridLayout_9")
self.sFlowTable = QtGui.QTableWidget(self.sFlow)
self.sFlowTable.setObjectName("sFlowTable")
self.sFlowTable.setColumnCount(0)
self.sFlowTable.setRowCount(0)
self.gridLayout_9.addWidget(self.sFlowTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.sFlow, "")
self.SSL = QtGui.QWidget()
self.SSL.setObjectName("SSL")
self.gridLayout_101 = QtGui.QGridLayout(self.SSL)
self.gridLayout_101.setObjectName("gridLayout_101")
self.SSLTable = QtGui.QTableWidget(self.SSL)
self.SSLTable.setObjectName("SSLTable")
self.SSLTable.setColumnCount(0)
self.SSLTable.setRowCount(0)
self.gridLayout_101.addWidget(self.SSLTable, 0, 0, 1, 1)
self.tabWidget.addTab(self.SSL, "")
self.verticalLayout.addWidget(self.tabWidget)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.hostLabel = QtGui.QLabel(self.centralwidget)
self.hostLabel.setObjectName("hostLabel")
self.horizontalLayout.addWidget(self.hostLabel)
self.hostComboBox = QtGui.QComboBox(self.centralwidget)
self.hostComboBox.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
self.hostComboBox.setObjectName("hostComboBox")
self.horizontalLayout.addWidget(self.hostComboBox)
self.intervalCheckBox = QtGui.QCheckBox(self.centralwidget)
self.intervalCheckBox.setObjectName("intervalCheckBox")
self.horizontalLayout.addWidget(self.intervalCheckBox)
self.intervalSpinBox = QtGui.QSpinBox(self.centralwidget)
self.intervalSpinBox.setMinimum(1)
self.intervalSpinBox.setMaximum(1000000)
self.intervalSpinBox.setObjectName("intervalSpinBox")
self.horizontalLayout.addWidget(self.intervalSpinBox)
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.fetchButton = QtGui.QPushButton(self.centralwidget)
self.fetchButton.setObjectName("fetchButton")
self.horizontalLayout.addWidget(self.fetchButton)
self.verticalLayout.addLayout(self.horizontalLayout)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 28))
self.menubar.setObjectName("menubar")
self.menuFile = QtGui.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionShow_Log = QtGui.QAction(MainWindow)
self.actionShow_Log.setObjectName("actionShow_Log")
self.actionNew_DB_Window = QtGui.QAction(MainWindow)
self.actionNew_DB_Window.setObjectName("actionNew_DB_Window")
self.actionPreferences = QtGui.QAction(MainWindow)
self.actionPreferences.setObjectName("actionPreferences")
self.actionQuit = QtGui.QAction(MainWindow)
self.actionQuit.setObjectName("actionQuit")
self.actionNew_Flow_Window = QtGui.QAction(MainWindow)
self.actionNew_Flow_Window.setObjectName("actionNew_Flow_Window")
self.menuFile.addAction(self.actionNew_DB_Window)
self.menuFile.addAction(self.actionNew_Flow_Window)
self.menuFile.addAction(self.actionShow_Log)
self.menuFile.addAction(self.actionPreferences)
self.menuFile.addSeparator()
self.menuFile.addAction(self.actionQuit)
self.menubar.addAction(self.menuFile.menuAction())
self.hostLabel.setBuddy(self.hostComboBox)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "OVSDB Monitor", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Bridge), QtGui.QApplication.translate("MainWindow", "Bridge", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Controller), QtGui.QApplication.translate("MainWindow", "Controller", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Interface), QtGui.QApplication.translate("MainWindow", "Interface", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Mirror), QtGui.QApplication.translate("MainWindow", "Mirror", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.NetFlow), QtGui.QApplication.translate("MainWindow", "NetFlow", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Open_vSwitch), QtGui.QApplication.translate("MainWindow", "Open_vSwitch", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Port), QtGui.QApplication.translate("MainWindow", "Port", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.QoS), QtGui.QApplication.translate("MainWindow", "QoS", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.Queue), QtGui.QApplication.translate("MainWindow", "Queue", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.sFlow), QtGui.QApplication.translate("MainWindow", "sFlow", None, QtGui.QApplication.UnicodeUTF8))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.SSL), QtGui.QApplication.translate("MainWindow", "SSL", None, QtGui.QApplication.UnicodeUTF8))
self.hostLabel.setText(QtGui.QApplication.translate("MainWindow", "Host", None, QtGui.QApplication.UnicodeUTF8))
self.intervalCheckBox.setText(QtGui.QApplication.translate("MainWindow", "Auto-refetch every", None, QtGui.QApplication.UnicodeUTF8))
self.intervalSpinBox.setSuffix(QtGui.QApplication.translate("MainWindow", "s", None, QtGui.QApplication.UnicodeUTF8))
self.fetchButton.setText(QtGui.QApplication.translate("MainWindow", "Refetch", None, QtGui.QApplication.UnicodeUTF8))
self.menuFile.setTitle(QtGui.QApplication.translate("MainWindow", "File", None, QtGui.QApplication.UnicodeUTF8))
self.actionShow_Log.setText(QtGui.QApplication.translate("MainWindow", "Show Log", None, QtGui.QApplication.UnicodeUTF8))
self.actionNew_DB_Window.setText(QtGui.QApplication.translate("MainWindow", "New DB Window", None, QtGui.QApplication.UnicodeUTF8))
self.actionPreferences.setText(QtGui.QApplication.translate("MainWindow", "Preferences", None, QtGui.QApplication.UnicodeUTF8))
self.actionQuit.setText(QtGui.QApplication.translate("MainWindow", "Quit", None, QtGui.QApplication.UnicodeUTF8))
self.actionNew_Flow_Window.setText(QtGui.QApplication.translate("MainWindow", "New Flow Window", None, QtGui.QApplication.UnicodeUTF8))

View File

@@ -1,62 +0,0 @@
ovsdbmonitor_pyfiles = \
ovsdb/ovsdbmonitor/OVEApp.py \
ovsdb/ovsdbmonitor/OVECommonWindow.py \
ovsdb/ovsdbmonitor/OVEConfig.py \
ovsdb/ovsdbmonitor/OVEConfigWindow.py \
ovsdb/ovsdbmonitor/OVEFetch.py \
ovsdb/ovsdbmonitor/OVEFlowWindow.py \
ovsdb/ovsdbmonitor/OVEHostWindow.py \
ovsdb/ovsdbmonitor/OVELogWindow.py \
ovsdb/ovsdbmonitor/OVELogger.py \
ovsdb/ovsdbmonitor/OVEMainWindow.py \
ovsdb/ovsdbmonitor/OVEStandard.py \
ovsdb/ovsdbmonitor/OVEUtil.py \
ovsdb/ovsdbmonitor/Ui_ConfigWindow.py \
ovsdb/ovsdbmonitor/Ui_FlowWindow.py \
ovsdb/ovsdbmonitor/Ui_HostWindow.py \
ovsdb/ovsdbmonitor/Ui_LogWindow.py \
ovsdb/ovsdbmonitor/Ui_MainWindow.py \
ovsdb/ovsdbmonitor/qt4reactor.py
EXTRA_DIST += \
$(ovsdbmonitor_pyfiles) \
ovsdb/ovsdbmonitor/COPYING \
ovsdb/ovsdbmonitor/ConfigWindow.ui \
ovsdb/ovsdbmonitor/FlowWindow.ui \
ovsdb/ovsdbmonitor/HostWindow.ui \
ovsdb/ovsdbmonitor/LogWindow.ui \
ovsdb/ovsdbmonitor/MainWindow.ui \
ovsdb/ovsdbmonitor/ovsdbmonitor.in \
ovsdb/ovsdbmonitor/ovsdbmonitor.desktop
MAN_ROOTS += ovsdb/ovsdbmonitor/ovsdbmonitor.1
ovsdbmonitordir = ${datadir}/ovsdbmonitor
desktopdir = ${datadir}/applications
if BUILD_OVSDBMONITOR
noinst_SCRIPTS += ovsdb/ovsdbmonitor/ovsdbmonitor
ovsdbmonitor_DATA = $(ovsdbmonitor_pyfiles)
desktop_DATA = ovsdb/ovsdbmonitor/ovsdbmonitor.desktop
install-exec-hook:
sed -e '/NOINSTALL/d' < ovsdb/ovsdbmonitor/ovsdbmonitor > ovsdb/ovsdbmonitor/ovsdbmonitor.tmp
chmod +x ovsdb/ovsdbmonitor/ovsdbmonitor.tmp
$(INSTALL_PROGRAM) ovsdb/ovsdbmonitor/ovsdbmonitor.tmp $(DESTDIR)$(bindir)/ovsdbmonitor
rm ovsdb/ovsdbmonitor/ovsdbmonitor.tmp
DISTCLEANFILES += \
ovsdb/ovsdbmonitor/ovsdbmonitor \
ovsdb/ovsdbmonitor/ovsdbmonitor.tmp
man_MANS += ovsdb/ovsdbmonitor/ovsdbmonitor.1
endif
UNINSTALL_LOCAL += ovsdbmonitor-uninstall-local
ovsdbmonitor-uninstall-local:
rm -f $(DESTDIR)$(bindir)/ovsdbmonitor
SUFFIXES += .ui .py
.ui.py:
$(PYUIC4) $< | sed 's/from PyQt4 import QtCore, QtGui/\
try:\
from OVEStandard import globalForcePySide\
if globalForcePySide:\
raise Exception()\
from PyQt4 import QtCore, QtGui\
except:\
from PySide import QtCore, QtGui/' > $@

View File

@@ -1,20 +0,0 @@
.\" -*- nroff -*-
.TH ovsdbmonitor 1 "May 2011" "Open vSwitch" "Open vSwitch Manual"
.
.SH NAME
ovsdbmonitor \- GUI tool for monitoring Open vSwitch installations
.
.SH SYNOPSIS
\fBovsdbmonitor\fR
.
.SH DESCRIPTION
The \fBovsdbmonitor\fR program is a Qt-based GUI tool for monitoring
and troubleshooting Open vSwitch. It presents GUI tables that
graphically represent an Open vSwitch kernel flow table (similar to
\fBovs\-dpctl dump\-flows\fR) and Open vSwitch database contents
(similar to \fBovs\-vsctl list \fItable\fR).
.SH "SEE ALSO"
.
\fBovsdb\-server\fR(1),
\fBovsdb\-client\fR(1),
and the OVSDB specification.

View File

@@ -1,7 +0,0 @@
[Desktop Entry]
Name=Open vSwitch DB Monitor
Comment=Monitor and troubleshoot local or remote Open vSwitch instances
Exec=ovsdbmonitor
Terminal=false
Type=Application
Categories=System;Monitor;

View File

@@ -1,39 +0,0 @@
#! @PYTHON@
# Copyright (c) 2010 Citrix Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Version 1.51
# 2010-05-07
import sys
sys.path.insert(0, "@ovsdbmonitordir@")
sys.path.insert(0, "@abs_top_srcdir@/ovsdb/ovsdbmonitor") # NOINSTALL
import sys, traceback
from pprint import pprint
from OVEApp import *
app = OVEApp()
try:
retVal = app.enter()
except Exception, e:
print str(e)
try:
trace = traceback.format_tb(sys.exc_info()[2])
except:
trace = ['Traceback not available']
print("".join(trace))
retVal = 1
sys.exit(retVal)

View File

@@ -1,331 +0,0 @@
# Copyright (c) 2001-2008 Twisted Matrix Laboratories.
# See LICENSE for details.
# The referred licence file contains:
#
#Copyright (c) 2001-2010
#Allen Short
#Andy Gayton
#Andrew Bennetts
#Antoine Pitrou
#Apple Computer, Inc.
#Benjamin Bruheim
#Bob Ippolito
#Canonical Limited
#Christopher Armstrong
#David Reid
#Donovan Preston
#Eric Mangold
#Eyal Lotem
#Itamar Shtull-Trauring
#James Knight
#Jason A. Mobarak
#Jean-Paul Calderone
#Jessica McKellar
#Jonathan Jacobs
#Jonathan Lange
#Jonathan D. Simms
#Jurgen Hermann
#Kevin Horn
#Kevin Turner
#Mary Gardiner
#Matthew Lefkowitz
#Massachusetts Institute of Technology
#Moshe Zadka
#Paul Swartz
#Pavel Pergamenshchik
#Ralph Meijer
#Sean Riley
#Software Freedom Conservancy
#Travis B. Hartwell
#Thijs Triemstra
#Thomas Herve
#Timothy Allen
#
#Permission is hereby granted, free of charge, to any person obtaining
#a copy of this software and associated documentation files (the
#"Software"), to deal in the Software without restriction, including
#without limitation the rights to use, copy, modify, merge, publish,
#distribute, sublicense, and/or sell copies of the Software, and to
#permit persons to whom the Software is furnished to do so, subject to
#the following conditions:
#
#The above copyright notice and this permission notice shall be
#included in all copies or substantial portions of the Software.
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
#LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
This module provides support for Twisted to be driven by the Qt mainloop.
In order to use this support, simply do the following::
| app = QApplication(sys.argv) # your code to init Qt
| import qt4reactor
| qt4reactor.install()
alternatively:
| from twisted.application import reactors
| reactors.installReactor('qt4')
Then use twisted.internet APIs as usual. The other methods here are not
intended to be called directly.
If you don't instantiate a QApplication or QCoreApplication prior to
installing the reactor, a QCoreApplication will be constructed
by the reactor. QCoreApplication does not require a GUI so trial testing
can occur normally.
Twisted can be initialized after QApplication.exec_() with a call to
reactor.runReturn(). calling reactor.stop() will unhook twisted but
leave your Qt application running
API Stability: stable
Maintainer: U{Glenn H Tarbox, PhD<mailto:glenn@tarbox.org>}
Previous maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
Original port to QT4: U{Gabe Rudy<mailto:rudy@goldenhelix.com>}
Subsequent port by therve
"""
__all__ = ['install']
import sys, time
try:
from zope.interface import implements
except:
print('+++ Python Zope interface module is required\n')
raise
try:
from OVEStandard import globalForcePySide
if globalForcePySide: raise Exception()
from PyQt4.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication
from PyQt4.QtCore import QEventLoop
except:
from PySide.QtCore import QSocketNotifier, QObject, SIGNAL, QTimer, QCoreApplication
from PySide.QtCore import QEventLoop
try:
from twisted.internet.interfaces import IReactorFDSet
from twisted.python import log
from twisted.internet.posixbase import PosixReactorBase
except:
print('+++ Python Twisted Conch module is required\n')
raise
class TwistedSocketNotifier(QSocketNotifier):
"""
Connection between an fd event and reader/writer callbacks.
"""
def __init__(self, reactor, watcher, type):
QSocketNotifier.__init__(self, watcher.fileno(), type)
self.reactor = reactor
self.watcher = watcher
self.fn = None
if type == QSocketNotifier.Read:
self.fn = self.read
elif type == QSocketNotifier.Write:
self.fn = self.write
QObject.connect(self, SIGNAL("activated(int)"), self.fn)
def shutdown(self):
QObject.disconnect(self, SIGNAL("activated(int)"), self.fn)
self.setEnabled(False)
self.fn = self.watcher = None
self.deleteLater()
def read(self, sock):
w = self.watcher
#self.setEnabled(False) # ??? do I need this?
def _read():
why = None
try:
why = w.doRead()
except:
log.err()
why = sys.exc_info()[1]
if why:
self.reactor._disconnectSelectable(w, why, True)
elif self.watcher:
pass
#self.setEnabled(True)
log.callWithLogger(w, _read)
self.reactor.reactorInvocation()
def write(self, sock):
w = self.watcher
self.setEnabled(False)
def _write():
why = None
try:
why = w.doWrite()
except:
log.err()
why = sys.exc_info()[1]
if why:
self.reactor._disconnectSelectable(w, why, False)
elif self.watcher:
self.setEnabled(True)
log.callWithLogger(w, _write)
self.reactor.reactorInvocation()
class fakeApplication(QEventLoop):
def __init__(self):
QEventLoop.__init__(self)
def exec_(self):
QEventLoop.exec_(self)
class QTReactor(PosixReactorBase):
"""
Qt based reactor.
"""
implements(IReactorFDSet)
_timer = None
def __init__(self):
self._reads = {}
self._writes = {}
self._timer=QTimer()
self._timer.setSingleShot(True)
if QCoreApplication.startingUp():
self.qApp=QCoreApplication([])
self._ownApp=True
else:
self.qApp = QCoreApplication.instance()
self._ownApp=False
self._blockApp = None
self._readWriteQ=[]
""" some debugging instrumentation """
self._doSomethingCount=0
PosixReactorBase.__init__(self)
def addReader(self, reader):
if not reader in self._reads:
self._reads[reader] = TwistedSocketNotifier(self, reader,
QSocketNotifier.Read)
def addWriter(self, writer):
if not writer in self._writes:
self._writes[writer] = TwistedSocketNotifier(self, writer,
QSocketNotifier.Write)
def removeReader(self, reader):
if reader in self._reads:
#self._reads[reader].shutdown()
#del self._reads[reader]
self._reads.pop(reader).shutdown()
def removeWriter(self, writer):
if writer in self._writes:
self._writes[writer].shutdown()
#del self._writes[writer]
self._writes.pop(writer)
def removeAll(self):
return self._removeAll(self._reads, self._writes)
def getReaders(self):
return self._reads.keys()
def getWriters(self):
return self._writes.keys()
def callLater(self,howlong, *args, **kargs):
rval = super(QTReactor,self).callLater(howlong, *args, **kargs)
self.reactorInvocation()
return rval
def crash(self):
super(QTReactor,self).crash()
def iterate(self,delay=0.0):
t=self.running # not sure I entirely get the state of running
self.running=True
self._timer.stop() # in case its not (rare?)
try:
if delay == 0.0:
self.reactorInvokePrivate()
self._timer.stop() # supports multiple invocations
else:
endTime = delay + time.time()
self.reactorInvokePrivate()
while True:
t = endTime - time.time()
if t <= 0.0: return
self.qApp.processEvents(QEventLoop.AllEvents |
QEventLoop.WaitForMoreEvents,t*1010)
finally:
self.running=t
def addReadWrite(self,t):
self._readWriteQ.append(t)
def runReturn(self, installSignalHandlers=True):
QObject.connect(self._timer, SIGNAL("timeout()"),
self.reactorInvokePrivate)
self.startRunning(installSignalHandlers=installSignalHandlers)
self._timer.start(0)
def run(self, installSignalHandlers=True):
try:
if self._ownApp:
self._blockApp=self.qApp
else:
self._blockApp = fakeApplication()
self.runReturn(installSignalHandlers)
self._blockApp.exec_()
finally:
self._timer.stop() # should already be stopped
def reactorInvocation(self):
self._timer.setInterval(0)
def reactorInvokePrivate(self):
if not self.running:
if self._blockApp is None:
# Andy's fix for Ctrl-C quit
self.qApp.quit()
else:
self._blockApp.quit()
self._doSomethingCount += 1
self.runUntilCurrent()
t = self.timeout()
if t is None: t=0.1
else: t = min(t,0.1)
self._timer.setInterval(int(t*1010))
self.qApp.processEvents() # could change interval
self._timer.start()
def doIteration(self):
assert False, "doiteration is invalid call"
def install():
"""
Configure the twisted mainloop to be run inside the qt mainloop.
"""
from twisted.internet import main
reactor = QTReactor()
main.installReactor(reactor)