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:
21
INSTALL
21
INSTALL
@@ -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
|
||||
=================================================================
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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
3
NEWS
@@ -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
3
README
@@ -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
|
||||
|
@@ -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
1
debian/.gitignore
vendored
@@ -16,6 +16,5 @@
|
||||
/openvswitch-switch
|
||||
/openvswitch-switch.copyright
|
||||
/openvswitch-test
|
||||
/ovsdbmonitor
|
||||
/python-openvswitch
|
||||
/tmp
|
||||
|
2
debian/automake.mk
vendored
2
debian/automake.mk
vendored
@@ -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
19
debian/control
vendored
@@ -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
|
||||
|
2
debian/ovsdbmonitor.install
vendored
2
debian/ovsdbmonitor.install
vendored
@@ -1,2 +0,0 @@
|
||||
usr/bin/ovsdbmonitor
|
||||
usr/share/ovsdbmonitor
|
1
debian/ovsdbmonitor.manpages
vendored
1
debian/ovsdbmonitor.manpages
vendored
@@ -1 +0,0 @@
|
||||
ovsdb/ovsdbmonitor/ovsdbmonitor.1
|
1
debian/rules
vendored
1
debian/rules
vendored
@@ -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
|
||||
|
@@ -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])
|
||||
|
@@ -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
|
||||
|
1
ovsdb/ovsdbmonitor/.gitignore
vendored
1
ovsdb/ovsdbmonitor/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/ovsdbmonitor
|
@@ -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.
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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>
|
@@ -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
|
@@ -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()
|
||||
|
@@ -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()"))
|
@@ -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()
|
||||
|
||||
|
@@ -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')
|
@@ -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)
|
@@ -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())
|
||||
}
|
||||
|
@@ -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()
|
@@ -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)
|
||||
|
@@ -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)
|
@@ -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
|
||||
|
@@ -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)]
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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))
|
||||
|
@@ -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/' > $@
|
@@ -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.
|
@@ -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;
|
@@ -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)
|
@@ -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)
|
Reference in New Issue
Block a user