4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
7 from sfa.rspecs.rspec_parser import parse_rspec
8 from sface.config import config
9 from sface.sfirenew import RenewWindow
10 from sface.sfiprocess import SfiProcess
11 from sface.screens.sfascreen import SfaScreen
12 from sface.sfidata import SfiData
15 GENI_STATUS_COLUMN = 1
17 class StatusView(QTreeView):
18 def __init__(self, parent):
19 QTreeView.__init__(self, parent)
21 self.setAnimated(True)
22 self.setItemsExpandable(True)
23 self.setRootIsDecorated(True)
24 self.setAlternatingRowColors(True)
25 self.setAttribute(Qt.WA_MacShowFocusRect, 0)
26 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
27 self.setToolTip("Double click on a row to change its status. Right click on a host to add a tag.")
29 class StatusFilterProxyModel(QSortFilterProxyModel):
30 def __init__(self, parent=None):
31 QSortFilterProxyModel.__init__(self, parent)
32 self.hostname_filter_regex = None
33 self.geni_status_filter = None
35 def setHostNameFilter(self, hostname):
36 self.hostname_filter_regex = QRegExp(hostname)
37 self.invalidateFilter()
39 def setNodeStatusFilter(self, status):
41 self.geni_status_filter = None
43 self.geni_status_filter = status
44 self.invalidateFilter()
46 def filterAcceptsRow(self, sourceRow, source_parent):
47 if self.hostname_filter_regex:
48 name_data = self.sourceModel().index(sourceRow, NAME_COLUMN, source_parent).data().toString()
49 if (self.hostname_filter_regex.indexIn(name_data) < 0):
51 if self.geni_status_filter:
52 geni_status_data = self.sourceModel().index(sourceRow, GENI_STATUS_COLUMN, source_parent).data().toString()
53 if (geni_status_data != self.geni_status_filter):
57 class StatusWidget(QWidget):
58 def __init__(self, parent):
59 QWidget.__init__(self, parent)
61 self.process = SfiProcess(self)
63 self.slicename = QLabel("", self)
64 self.updateSliceName()
65 self.slicename.setScaledContents(False)
66 filterlabel = QLabel ("Filter: ", self)
67 filterbox = QComboBox(self)
68 filterbox.addItems(["all", "ready", "failed"])
69 searchlabel = QLabel ("Search: ", self)
70 searchlabel.setScaledContents(False)
71 searchbox = QLineEdit(self)
72 searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0)
74 self.urn = QLabel("", self)
75 self.login = QLabel("", self)
77 toplayout1 = QHBoxLayout()
78 toplayout1.addWidget(self.slicename, 0, Qt.AlignLeft)
79 toplayout1.addStretch()
80 toplayout1.addWidget(filterlabel, 0, Qt.AlignRight)
81 toplayout1.addWidget(filterbox, 0, Qt.AlignRight)
82 toplayout1.addWidget(searchlabel, 0, Qt.AlignRight)
83 toplayout1.addWidget(searchbox, 0, Qt.AlignRight)
85 toplayout2 = QHBoxLayout()
86 toplayout2.addWidget(self.urn, 0, Qt.AlignRight)
87 toplayout2.addWidget(self.login, 0, Qt.AlignRight)
88 toplayout2.addStretch()
90 toplayout = QVBoxLayout()
91 toplayout.addLayout(toplayout1)
92 toplayout.addLayout(toplayout2)
94 self.statusView = StatusView(self)
95 self.statusModel = QStandardItemModel(0, 4, self)
96 self.filterModel = StatusFilterProxyModel(self)
98 refresh = QPushButton("Refresh", self)
99 refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
101 bottomlayout = QHBoxLayout()
102 bottomlayout.addWidget(refresh, 0, Qt.AlignLeft)
103 bottomlayout.addStretch()
105 layout = QVBoxLayout()
106 layout.addLayout(toplayout)
107 layout.addWidget(self.statusView)
108 layout.addLayout(bottomlayout)
109 self.setLayout(layout)
110 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
112 self.connect(refresh, SIGNAL('clicked()'), self.refresh)
113 self.connect(searchbox, SIGNAL('textChanged(QString)'), self.search)
114 self.connect(filterbox, SIGNAL('currentIndexChanged(QString)'), self.filter)
118 def sliverStatusFinished(self):
119 self.disconnect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
121 faultString = self.process.getFaultString()
123 self.setStatus("<font color='green'>Sliver status refreshed.</font>", timeout=5000)
125 self.setStatus("<font color='red'>Sliver status failed: %s</font>" % (faultString))
129 def setStatus(self, msg, timeout=None):
130 self.parent().setStatus(msg, timeout)
132 def checkRunningProcess(self):
133 if self.process.isRunning():
134 self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
138 def search(self, search_string):
139 self.filterModel.setHostNameFilter(str(search_string))
141 def filter(self, filter_string):
142 self.filterModel.setNodeStatusFilter(str(filter_string))
144 def itemStatus(self, item):
145 statusItem = item.parent().child(item.row(), MEMBERSHIP_STATUS_COLUMN)
146 return str(statusItem.data(Qt.DisplayRole).toString())
148 def itemText(self, item):
149 return str(item.data(Qt.DisplayRole).toString())
152 if not config.getSlice():
153 self.setStatus("<font color='red'>Slice not set yet!</font>")
156 if self.process.isRunning():
157 self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
160 self.connect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
162 self.process.sliverStatus()
163 self.setStatus("Refreshing Sliver Status. This will take some time...")
165 def updateView(self):
166 self.statusModel.clear()
168 sliverStatus = SfiData().getSliverStatus()
172 geni_urn = sliverStatus.get("geni_urn","")
173 self.urn.setText("URN: " + geni_urn)
175 login = sliverStatus.get("pl_login","")
176 self.login.setText("Login: " + login)
178 rootItem = self.statusModel.invisibleRootItem()
180 resources = sliverStatus.get("geni_resources", [])
182 for resource in resources:
183 # try to pick the most useful thing
184 name = resource.get("pl_hostname","")
186 name = resource.get("geni_urn","")
191 status = resource.get("geni_status","")
192 error = resource.get("error", "")
193 lastContact = resource.get("pl_last_contact", "")
195 # some of these return None, and we need to convert that back to
204 nameItem = QStandardItem(QString(name))
205 statusItem = QStandardItem(QString(status))
206 errorItem = QStandardItem(QString(error))
207 lastContact = QStandardItem(QString(lastContact))
208 rootItem.appendRow([nameItem, statusItem, errorItem, lastContact])
210 self.filterModel.setSourceModel(self.statusModel)
211 self.filterModel.setDynamicSortFilter(True)
213 headers = QStringList() << "URN" << "Status" << "Error" << "Last Contact"
214 self.statusModel.setHorizontalHeaderLabels(headers)
216 self.statusView.setModel(self.filterModel)
217 self.statusView.expandAll()
218 self.statusView.resizeColumnToContents(0)
219 self.statusView.collapseAll()
221 def updateSliceName(self):
222 self.slicename.setText("Slice : %s" % (config.getSlice() or "None"))
224 class StatusScreen(SfaScreen):
225 def __init__(self, parent):
226 SfaScreen.__init__(self, parent)
228 slice = StatusWidget(self)
229 self.init(slice, "Status", "Sliver Status")
231 def rspecUpdated(self):
234 def configurationChanged(self):
235 self.widget.updateSliceName()
236 self.widget.updateView()
238 def nodeSelectionChanged(self, hostname):