4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
7 from sface.config import config
8 from sface.sfirenew import RenewWindow
9 from sface.sfiprocess import SfiProcess
10 from sface.screens.sfascreen import SfaScreen
11 from sface.sfidata import SfiData
14 GENI_STATUS_COLUMN = 1
16 class StatusView(QTreeView):
17 def __init__(self, parent):
18 QTreeView.__init__(self, parent)
20 self.setAnimated(True)
21 self.setItemsExpandable(True)
22 self.setRootIsDecorated(True)
23 self.setAlternatingRowColors(True)
24 self.setAttribute(Qt.WA_MacShowFocusRect, 0)
25 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
26 self.setToolTip("Double click on a row to change its status. Right click on a host to add a tag.")
28 class StatusFilterProxyModel(QSortFilterProxyModel):
29 def __init__(self, parent=None):
30 QSortFilterProxyModel.__init__(self, parent)
31 self.hostname_filter_regex = None
32 self.geni_status_filter = None
34 def setHostNameFilter(self, hostname):
35 self.hostname_filter_regex = QRegExp(hostname)
36 self.invalidateFilter()
38 def setNodeStatusFilter(self, status):
40 self.geni_status_filter = None
42 self.geni_status_filter = status
43 self.invalidateFilter()
45 def filterAcceptsRow(self, sourceRow, source_parent):
46 if self.hostname_filter_regex:
47 name_data = self.sourceModel().index(sourceRow, NAME_COLUMN, source_parent).data().toString()
48 if (self.hostname_filter_regex.indexIn(name_data) < 0):
50 if self.geni_status_filter:
51 geni_status_data = self.sourceModel().index(sourceRow, GENI_STATUS_COLUMN, source_parent).data().toString()
52 if (geni_status_data != self.geni_status_filter):
56 class StatusWidget(QWidget):
57 def __init__(self, parent):
58 QWidget.__init__(self, parent)
60 self.process = SfiProcess(self)
62 self.slicename = QLabel("", self)
63 self.updateSliceName()
64 self.slicename.setScaledContents(False)
65 filterlabel = QLabel ("Filter: ", self)
66 filterbox = QComboBox(self)
67 filterbox.addItems(["all", "ready", "failed"])
68 searchlabel = QLabel ("Search: ", self)
69 searchlabel.setScaledContents(False)
70 searchbox = QLineEdit(self)
71 searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0)
73 self.urn = QLabel("", self)
74 self.login = QLabel("", self)
76 toplayout1 = QHBoxLayout()
77 toplayout1.addWidget(self.slicename, 0, Qt.AlignLeft)
78 toplayout1.addStretch()
79 toplayout1.addWidget(filterlabel, 0, Qt.AlignRight)
80 toplayout1.addWidget(filterbox, 0, Qt.AlignRight)
81 toplayout1.addWidget(searchlabel, 0, Qt.AlignRight)
82 toplayout1.addWidget(searchbox, 0, Qt.AlignRight)
84 toplayout2 = QHBoxLayout()
85 toplayout2.addWidget(self.urn, 0, Qt.AlignRight)
86 toplayout2.addWidget(self.login, 0, Qt.AlignRight)
87 toplayout2.addStretch()
89 toplayout = QVBoxLayout()
90 toplayout.addLayout(toplayout1)
91 toplayout.addLayout(toplayout2)
93 self.statusView = StatusView(self)
94 self.statusModel = QStandardItemModel(0, 4, self)
95 self.filterModel = StatusFilterProxyModel(self)
97 refresh = QPushButton("Refresh", self)
98 refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
100 bottomlayout = QHBoxLayout()
101 bottomlayout.addWidget(refresh, 0, Qt.AlignLeft)
102 bottomlayout.addStretch()
104 layout = QVBoxLayout()
105 layout.addLayout(toplayout)
106 layout.addWidget(self.statusView)
107 layout.addLayout(bottomlayout)
108 self.setLayout(layout)
109 self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
111 self.connect(refresh, SIGNAL('clicked()'), self.refresh)
112 self.connect(searchbox, SIGNAL('textChanged(QString)'), self.search)
113 self.connect(filterbox, SIGNAL('currentIndexChanged(QString)'), self.filter)
117 def sliverStatusFinished(self):
118 self.disconnect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
120 faultString = self.process.getFaultString()
122 self.setStatus("<font color='green'>Sliver status refreshed.</font>", timeout=5000)
124 self.setStatus("<font color='red'>Sliver status failed: %s</font>" % (faultString))
128 def setStatus(self, msg, timeout=None):
129 self.parent().setStatus(msg, timeout)
131 def checkRunningProcess(self):
132 if self.process.isRunning():
133 self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
137 def search(self, search_string):
138 self.filterModel.setHostNameFilter(str(search_string))
140 def filter(self, filter_string):
141 self.filterModel.setNodeStatusFilter(str(filter_string))
143 def itemStatus(self, item):
144 statusItem = item.parent().child(item.row(), MEMBERSHIP_STATUS_COLUMN)
145 return str(statusItem.data(Qt.DisplayRole).toString())
147 def itemText(self, item):
148 return str(item.data(Qt.DisplayRole).toString())
151 if not config.getSlice():
152 self.setStatus("<font color='red'>Slice not set yet!</font>")
155 if self.process.isRunning():
156 self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
159 self.connect(self.process, SIGNAL('finished()'), self.sliverStatusFinished)
161 self.process.sliverStatus()
162 self.setStatus("Refreshing Sliver Status. This will take some time...")
164 def updateView(self):
165 self.statusModel.clear()
167 sliverStatus = SfiData().getSliverStatus()
171 geni_urn = sliverStatus.get("geni_urn","")
172 self.urn.setText("URN: " + geni_urn)
174 login = sliverStatus.get("pl_login","")
175 self.login.setText("Login: " + login)
177 rootItem = self.statusModel.invisibleRootItem()
179 resources = sliverStatus.get("geni_resources", [])
181 for resource in resources:
182 # try to pick the most useful thing
183 name = resource.get("pl_hostname","")
185 name = resource.get("geni_urn","")
190 status = resource.get("geni_status","")
191 error = resource.get("error", "")
192 lastContact = resource.get("pl_last_contact", "")
194 # some of these return None, and we need to convert that back to
203 nameItem = QStandardItem(QString(name))
204 statusItem = QStandardItem(QString(status))
205 errorItem = QStandardItem(QString(error))
206 lastContact = QStandardItem(QString(lastContact))
207 rootItem.appendRow([nameItem, statusItem, errorItem, lastContact])
209 self.filterModel.setSourceModel(self.statusModel)
210 self.filterModel.setDynamicSortFilter(True)
211 self.filterModel.sort(NAME_COLUMN)
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):