import datetime
import os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from sface.config import config
from sface.sfirenew import RenewWindow
from sface.sfiprocess import SfiProcess
from sface.screens.sfascreen import SfaScreen
from sface.sfidata import SfiData
NAME_COLUMN = 0
GENI_STATUS_COLUMN = 1
class StatusView(QTreeView):
def __init__(self, parent):
QTreeView.__init__(self, parent)
self.setAnimated(True)
self.setItemsExpandable(True)
self.setRootIsDecorated(True)
self.setAlternatingRowColors(True)
self.setAttribute(Qt.WA_MacShowFocusRect, 0)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setToolTip("Double click on a row to change its status. Right click on a host to add a tag.")
class StatusFilterProxyModel(QSortFilterProxyModel):
def __init__(self, parent=None):
QSortFilterProxyModel.__init__(self, parent)
self.hostname_filter_regex = None
self.geni_status_filter = None
def setHostNameFilter(self, hostname):
self.hostname_filter_regex = QRegExp(hostname)
self.invalidateFilter()
def setNodeStatusFilter(self, status):
if (status == "all"):
self.geni_status_filter = None
else:
self.geni_status_filter = status
self.invalidateFilter()
def filterAcceptsRow(self, sourceRow, source_parent):
if self.hostname_filter_regex:
name_data = self.sourceModel().index(sourceRow, NAME_COLUMN, source_parent).data().toString()
if (self.hostname_filter_regex.indexIn(name_data) < 0):
return False
if self.geni_status_filter:
geni_status_data = self.sourceModel().index(sourceRow, GENI_STATUS_COLUMN, source_parent).data().toString()
if (geni_status_data != self.geni_status_filter):
return False
return True
class StatusWidget(QWidget):
def __init__(self, parent):
QWidget.__init__(self, parent)
self.process = SfiProcess(self)
self.slicename = QLabel("", self)
self.updateSliceName()
self.slicename.setScaledContents(False)
filterlabel = QLabel ("Filter: ", self)
filterbox = QComboBox(self)
filterbox.addItems(["all", "ready", "failed"])
searchlabel = QLabel ("Search: ", self)
searchlabel.setScaledContents(False)
searchbox = QLineEdit(self)
searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0)
self.urn = QLabel("", self)
self.login = QLabel("", self)
toplayout1 = QHBoxLayout()
toplayout1.addWidget(self.slicename, 0, Qt.AlignLeft)
toplayout1.addStretch()
toplayout1.addWidget(filterlabel, 0, Qt.AlignRight)
toplayout1.addWidget(filterbox, 0, Qt.AlignRight)
toplayout1.addWidget(searchlabel, 0, Qt.AlignRight)
toplayout1.addWidget(searchbox, 0, Qt.AlignRight)
toplayout2 = QHBoxLayout()
toplayout2.addWidget(self.urn, 0, Qt.AlignRight)
toplayout2.addWidget(self.login, 0, Qt.AlignRight)
toplayout2.addStretch()
toplayout = QVBoxLayout()
toplayout.addLayout(toplayout1)
toplayout.addLayout(toplayout2)
self.statusView = StatusView(self)
self.statusModel = QStandardItemModel(0, 4, self)
self.filterModel = StatusFilterProxyModel(self)
refresh = QPushButton("Refresh", self)
refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
bottomlayout = QHBoxLayout()
bottomlayout.addWidget(refresh, 0, Qt.AlignLeft)
bottomlayout.addStretch()
layout = QVBoxLayout()
layout.addLayout(toplayout)
layout.addWidget(self.statusView)
layout.addLayout(bottomlayout)
self.setLayout(layout)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.connect(refresh, SIGNAL('clicked()'), self.refresh)
self.connect(searchbox, SIGNAL('textChanged(QString)'), self.search)
self.connect(filterbox, SIGNAL('currentIndexChanged(QString)'), self.filter)
self.updateView()
def sliverStatusFinished(self):
self.disconnect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
faultString = self.process.getFaultString()
if not faultString:
self.setStatus("Sliver status refreshed.", timeout=5000)
else:
self.setStatus("Sliver status failed: %s" % (faultString))
self.updateView()
def setStatus(self, msg, timeout=None):
self.parent().setStatus(msg, timeout)
def checkRunningProcess(self):
if self.process.isRunning():
self.setStatus("There is already a process running. Please wait.")
return True
return False
def search(self, search_string):
self.filterModel.setHostNameFilter(str(search_string))
def filter(self, filter_string):
self.filterModel.setNodeStatusFilter(str(filter_string))
def itemStatus(self, item):
statusItem = item.parent().child(item.row(), MEMBERSHIP_STATUS_COLUMN)
return str(statusItem.data(Qt.DisplayRole).toString())
def itemText(self, item):
return str(item.data(Qt.DisplayRole).toString())
def refresh(self):
if not config.getSlice():
self.setStatus("Slice not set yet!")
return
if self.process.isRunning():
self.setStatus("There is already a process running. Please wait.")
return
self.connect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
self.process.sliverStatus()
self.setStatus("Refreshing Sliver Status. This will take some time...")
def updateView(self):
self.statusModel.clear()
sliverStatus = SfiData().getSliverStatus()
if not sliverStatus:
return None
geni_urn = sliverStatus.get("geni_urn","")
self.urn.setText("URN: " + geni_urn)
login = sliverStatus.get("pl_login","")
self.login.setText("Login: " + login)
rootItem = self.statusModel.invisibleRootItem()
resources = sliverStatus.get("geni_resources", [])
for resource in resources:
# try to pick the most useful thing
name = resource.get("pl_hostname","")
if not name:
name = resource.get("geni_urn","")
if not name:
continue
status = resource.get("geni_status","")
error = resource.get("error", "")
lastContact = resource.get("pl_last_contact", "")
# some of these return None, and we need to convert that back to
# an empty string
if not status:
status = ""
if not error:
error = ""
if not lastContact:
lastContact = ""
nameItem = QStandardItem(QString(name))
statusItem = QStandardItem(QString(status))
errorItem = QStandardItem(QString(error))
lastContact = QStandardItem(QString(lastContact))
rootItem.appendRow([nameItem, statusItem, errorItem, lastContact])
self.filterModel.setSourceModel(self.statusModel)
self.filterModel.setDynamicSortFilter(True)
self.filterModel.sort(NAME_COLUMN)
headers = QStringList() << "URN" << "Status" << "Error" << "Last Contact"
self.statusModel.setHorizontalHeaderLabels(headers)
self.statusView.setModel(self.filterModel)
self.statusView.expandAll()
self.statusView.resizeColumnToContents(0)
self.statusView.collapseAll()
def updateSliceName(self):
self.slicename.setText("Slice : %s" % (config.getSlice() or "None"))
class StatusScreen(SfaScreen):
def __init__(self, parent):
SfaScreen.__init__(self, parent)
slice = StatusWidget(self)
self.init(slice, "Status", "Sliver Status")
def rspecUpdated(self):
pass
def configurationChanged(self):
self.widget.updateSliceName()
self.widget.updateView()
def nodeSelectionChanged(self, hostname):
pass