check in slice user management screen
authorsmbaker <smbaker@fc8clean.lan>
Wed, 24 Aug 2011 01:31:00 +0000 (18:31 -0700)
committersmbaker <smbaker@fc8clean.lan>
Wed, 24 Aug 2011 01:31:00 +0000 (18:31 -0700)
sface/screens/userscreen.py [new file with mode: 0644]

diff --git a/sface/screens/userscreen.py b/sface/screens/userscreen.py
new file mode 100644 (file)
index 0000000..53c279f
--- /dev/null
@@ -0,0 +1,301 @@
+
+import datetime
+import os
+import pickle
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+
+from sfa.util.record import SfaRecord, SliceRecord, AuthorityRecord, UserRecord
+from sface.config import config
+from sface.sfiprocess import SfiProcess
+from sface.screens.sfascreen import SfaScreen
+
+NAME_COLUMN = 0
+ROLE_COLUMN = 1
+MEMBERSHIP_STATUS_COLUMN = 2
+SERVER_MEMBERSHIP_STATUS_COLUMN = 3
+
+user_status = { "in": "Already Selected",
+                "out": "Not Selected",
+                "add": "To be Added",
+                "remove": "To be Removed"}
+
+class UserView(QTableView):
+    def __init__(self, parent=None):
+        QTableView.__init__(self, parent)
+
+        self.setSelectionBehavior(QAbstractItemView.SelectRows)
+        self.setSelectionMode(QAbstractItemView.SingleSelection)
+        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.")
+
+    def mouseDoubleClickEvent(self, event):
+        index = self.currentIndex()
+        model = index.model()
+        status_index = model.index(index.row(), MEMBERSHIP_STATUS_COLUMN, index.parent())
+        status_data = status_index.data().toString()
+        server_status_data = model.index(index.row(), SERVER_MEMBERSHIP_STATUS_COLUMN, index.parent()).data().toString()
+        node_index = model.index(index.row(), NAME_COLUMN, index.parent())
+        node_data = node_index.data().toString()
+
+        # This is a hostname
+        if status_data == user_status['in']:
+            model.setData(status_index, QString(user_status['remove']))
+        elif status_data == user_status['out']:
+            model.setData(status_index, QString(user_status['add']))
+        elif status_data in (user_status['add'], user_status['remove']):
+            if server_status_data == user_status["in"]:
+                model.setData(status_index, QString(user_status['in']))
+            else:
+                model.setData(status_index, QString(user_status['out']))
+
+        model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), node_index, node_index)
+
+    def currentChanged(self, current, previous):
+        model = current.model()
+        node_index = model.index(current.row(), 0, current.parent())
+        node_data = node_index.data().toString()
+        self.emit(SIGNAL('hostnameClicked(QString)'), node_data)
+
+
+class UsersWidget(QWidget):
+    def __init__(self, parent):
+        QWidget.__init__(self, parent)
+
+        self.process = SfiProcess(self)
+
+        self.slicename = QLabel("", self)
+        self.updateSliceName()
+        self.slicename.setScaledContents(False)
+        searchlabel = QLabel ("Search: ", self)
+        searchlabel.setScaledContents(False)
+        searchbox = QLineEdit(self)
+        searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0)
+
+        toplayout = QHBoxLayout()
+        toplayout.addWidget(self.slicename, 0, Qt.AlignLeft)
+        toplayout.addStretch()
+        toplayout.addWidget(searchlabel, 0, Qt.AlignRight)
+        toplayout.addWidget(searchbox, 0, Qt.AlignRight)
+
+        self.userView = UserView()
+        #self.userView.setSelectionBehavior(QAbstractItemView.SelectRows)
+        #self.userView.setSelectionMode(QAbstractItemView.SingleSelection)
+
+        refresh = QPushButton("Refresh", self)
+        refresh.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
+        submit = QPushButton("Submit", self)
+        submit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
+
+        bottomlayout = QHBoxLayout()
+        bottomlayout.addWidget(refresh, 0, Qt.AlignLeft)
+        bottomlayout.addStretch()
+        bottomlayout.addWidget(submit, 0, Qt.AlignRight)
+
+        layout = QVBoxLayout()
+        layout.addLayout(toplayout)
+        layout.addWidget(self.userView)
+        layout.addLayout(bottomlayout)
+        self.setLayout(layout)
+        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+
+        self.userModel = QStandardItemModel(0, 4, self)
+
+        self.connect(refresh, SIGNAL('clicked()'), self.refresh)
+        self.connect(submit, SIGNAL('clicked()'), self.submit)
+
+        self.updateView()
+
+    def submitFinished(self):
+        self.setStatus("<font color='green'>Slice data submitted.</font>")
+        QTimer.singleShot(1000, self.refresh)
+
+    def getSliceRecordFinished(self):
+        self.setStatus("<font color='green'>Authority data refreshed.</font>", timeout=5000)
+        self.refreshAuthority()
+
+    def getAuthorityRecordFinished(self):
+        self.setStatus("<font color='green'>Slice data refreshed.</font>", timeout=5000)
+        self.updateView()
+        #self.parent().signalAll("usersUpdated")
+
+    def readSliceRecord(self):
+        rec_file = config.getSliceRecordFile()
+        if os.path.exists(rec_file):
+            xml = open(rec_file).read()
+            rec = SliceRecord()
+            rec.load_from_string(xml)
+            return rec
+        return None
+
+    def readAuthorityRecord(self):
+        rec_file = config.getAuthorityRecordFile()
+        if os.path.exists(rec_file):
+            xml = open(rec_file).read()
+            rec = AuthorityRecord()
+            rec.load_from_string(xml)
+            return rec
+        return None
+
+    def readUserRecord(self, i):
+        rec_file = config.getAuthorityListFile(i)
+        if os.path.exists(rec_file):
+            xml = open(rec_file).read()
+            rec = UserRecord()
+            rec.load_from_string(xml)
+            return rec
+        return None
+
+    def setStatus(self, msg, timeout=None):
+        self.parent().setStatus(msg, timeout)
+
+    def checkRunningProcess(self):
+        if self.process.isRunning():
+            self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
+            return True
+        return False
+
+    def submit(self):
+        if self.checkRunningProcess():
+            return
+
+        rec = self.readSliceRecord()
+        change = self.process_table(rec)
+
+        if not change:
+            self.setStatus("<font color=red>No change in slice data. Not submitting!</font>", timeout=3000)
+            return
+
+        rec_file = config.getSliceRecordFile()
+        file(rec_file, "w").write(rec.save_to_string())
+
+        self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
+        self.connect(self.process, SIGNAL('finished()'), self.submitFinished)
+
+        self.process.updateRecord(rec_file)
+        self.setStatus("Sending slice record. This will take some time...")
+
+    def refresh(self):
+        if not config.getSlice():
+            self.setStatus("<font color='red'>Slice not set yet!</font>")
+            return
+
+        if self.process.isRunning():
+            self.setStatus("<font color='red'>There is already a process running. Please wait.</font>")
+            return
+
+        self.disconnect(self.process, SIGNAL('finished()'), self.submitFinished)
+        self.connect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
+
+        self.process.getSliceRecord()
+        self.setStatus("Refreshing slice record. This will take some time...")
+
+    def refreshAuthority(self):
+        self.disconnect(self.process, SIGNAL('finished()'), self.getSliceRecordFinished)
+        self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished)
+
+        self.process.listRecords(config.getAuthority(), "user", config.getAuthorityListFile())
+        self.setStatus("Refreshing user records. This will take some time...")
+
+    def addTableItem(self, table, row, col, val, data=None, readonly=True):
+        item = QTableWidgetItem(str(val))
+        if readonly:
+            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+        if data:
+            if not isinstance(data, str):
+               data = pickle.dumps(data)
+            item.setData(Qt.UserRole, QVariant(data))
+        table.setItem(row, col, item)
+
+    def updateModel(self):
+        self.userModel.clear()
+
+        sliceRec = self.readSliceRecord()
+        if not sliceRec:
+            return None
+
+        added_persons = []
+        slice_persons = []
+
+        for pi in sliceRec.get_field("PI"):
+            name = str(pi)
+            if not name in added_persons:
+                 slice_persons.append({"name": name, "role": "PI", "member": user_status["in"]})
+                 added_persons.append(name)
+        for researcher in sliceRec.get_field("researcher"):
+            name = str(researcher)
+            if not name in added_persons:
+                 slice_persons.append({"name": name, "role": "researcher", "member": user_status["in"]})
+                 added_persons.append(name)
+
+        i=1
+        while (os.path.exists(config.getAuthorityListFile(i))):
+            rec = self.readUserRecord(i)
+            if rec:
+                name = str(rec.get_name())
+                if not name in added_persons:
+                    slice_persons.append({"name": name, "role": "", "member": user_status["out"]})
+                    added_persons.append(name)
+            i=i+1
+
+        rootItem = self.userModel.invisibleRootItem()
+
+        for person in slice_persons:
+            rootItem.appendRow([QStandardItem(QString(person["name"])),
+                               QStandardItem(QString(person["role"])),
+                               QStandardItem(QString(person["member"])),
+                               QStandardItem(QString(person["member"]))])
+
+        headers = QStringList() << "User Name" << "Role" << "Status" << "ServerStatus"
+        self.userModel.setHorizontalHeaderLabels(headers)
+
+    def updateView(self):
+        self.updateModel()
+
+        self.userView.setModel(self.userModel)
+        self.userView.hideColumn(SERVER_MEMBERSHIP_STATUS_COLUMN)
+        self.userView.resizeColumnToContents(0)
+
+    def updateSliceName(self):
+        self.slicename.setText("Slice : %s" % (config.getSlice() or "None"))
+
+    def nodeSelectionChanged(self, hostname):
+        self.parent().nodeSelectionChanged(hostname)
+
+    def process_table(self, slicerec):
+        change = False
+
+        item = self.userModel.invisibleRootItem()
+        children = item.rowCount()
+        for row in range(0, children):
+            childName = str(item.child(row, NAME_COLUMN).data(Qt.DisplayRole).toString())
+            childStatus = str(item.child(row, MEMBERSHIP_STATUS_COLUMN).data(Qt.DisplayRole).toString())
+
+            if (childStatus == user_status['add']):
+                slicerec.get_field("researcher").append(childName)
+                change = True
+            elif (childStatus == user_status['remove']):
+                if childName in slicerec.get_field("PI"):
+                     slicerec.get_field("PI").remove(childName)
+                if childName in slicerec.get_field("researcher"):
+                     slicerec.get_field("researcher").remove(childName)
+                change = True
+
+        print "XXX", slicerec.get_field("researcher")
+        return change
+
+
+class MainScreen(SfaScreen):
+    def __init__(self, parent):
+        SfaScreen.__init__(self, parent)
+
+        slice = UsersWidget(self)
+        self.init(slice, "Users", "OneLab SFA crawler")
+
+    def configurationChanged(self):
+        self.widget.updateSliceName()
+        self.widget.updateView()
+
+