import calendar import datetime import os import re import sys import time from PyQt4.QtCore import * from PyQt4.QtGui import * from sface.config import config from sface.sfiprocess import SfiProcess #from sface.sfithread import SfiThread from sface.sliceview import SliceView, SliceModel class SfiRenewer(QObject): def __init__(self, hrn, newExpiration, parent=None): QObject.__init__(self, parent) self.hrn = hrn self.newExpiration = newExpiration self.faultString = None self.renewProcess = SfiProcess(self) self.connect(self.renewProcess, SIGNAL('finished()'), self.finishedGetRecord) self.renewProcess.getRecord(hrn=hrn, filename="/tmp/slicerecord") def finishedGetRecord(self): self.faultString = self.renewProcess.getFaultString() if self.faultString: self.emitFinished("fault", self.faultString) return f = open("/tmp/slicerecord", "r") data = f.read() f.close() # find the expiration time exp = re.compile('expires="[^"]*"') if exp.search(data)==None: # didn't find it self.faultString = "failed to find expiration in slice record" self.emitFinished("failure", self.faultString) return # change the expiration time delta = 24*60*60 # always extend the slice by one extra day to cover slop for time zone differences data = exp.sub('expires="' + str(calendar.timegm(self.newExpiration.timetuple())+delta) + '"', data) open("/tmp/slicerecord", "w").write(data) self.disconnect(self.renewProcess, SIGNAL('finished()'), self.finishedGetRecord) self.connect(self.renewProcess, SIGNAL('finished()'), self.finishedUpdateRecord) self.renewProcess.updateRecord("/tmp/slicerecord") def finishedUpdateRecord(self): self.faultString = self.renewProcess.getFaultString() if self.faultString: self.emitFinished("fault", self.faultString) return # we have to force sfi.py to download an updated slice credential sliceCredName = config.fullpath("slice_" + self.hrn.split(".")[-1] + ".cred") if os.path.exists(sliceCredName): os.remove(sliceCredName) open("/tmp/expiration", "w").write(self.newExpiration.strftime("%Y-%m-%dT%H:%M:%SZ")) # call renewSlivers on the aggregate self.disconnect(self.renewProcess, SIGNAL('finished()'), self.finishedUpdateRecord) self.connect(self.renewProcess, SIGNAL('finished()'), self.finishedRenewSlivers) self.renewProcess.renewSlivers(self.newExpiration.strftime("%Y-%m-%dT%H:%M:%SZ"), slice = self.hrn) def finishedRenewSlivers(self): self.faultString = self.renewProcess.getFaultString() if self.faultString: self.emitFinished("fault", self.faultString) return self.emitFinished("success") def emitFinished(self, status, statusMsg=None): self.status = status self.statusMsg = statusMsg self.emit(SIGNAL("finished()")) def getFaultString(self): return self.faultString class RenewWindow(QDialog): def __init__(self, batch=False, parent=None): super(RenewWindow, self).__init__(parent) self.setWindowTitle("Renew Slivers") self.batch = batch self.renewProcess = None durationLabel = QLabel("Duration:") self.duration = QComboBox() self.expirations = [] durations = ( (1, "One Week"), (2, "Two Weeks"), (3, "Three Weeks"), (4, "One Month") ) now = datetime.datetime.utcnow() for (weeks, desc) in durations: exp = now + datetime.timedelta(days = weeks * 7) desc = desc + " " + exp.strftime("%Y-%m-%d %H:%M:%S") self.expirations.append(exp) self.duration.addItem(desc) self.duration.setCurrentIndex(0) if self.batch: sliceLabel = QLabel("Slices:") self.sliceView = SliceView() self.status = QLabel("") self.status.setMaximumWidth(640) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setDefault(True) if not self.batch: self.buttonBox.addButton("Batch", QDialogButtonBox.ActionRole) layout = QVBoxLayout() layout.addWidget(durationLabel) layout.addWidget(self.duration) if self.batch: layout.addWidget(sliceLabel) layout.addWidget(self.sliceView) layout.addWidget(self.status) layout.addWidget(self.buttonBox) self.setLayout(layout) self.connect(self.buttonBox, SIGNAL("accepted()"), self, SLOT("accept()")) self.connect(self.buttonBox, SIGNAL("rejected()"), self, SLOT("reject()")) self.connect(self.buttonBox, SIGNAL("clicked(QAbstractButton *)"), self.clicked) if self.batch: self.sliceModel = SliceModel() self.refreshAuthority() def clicked(self, button): if button.text() == "Batch": # close ourself, and reopen the batch renew window self.close() dlg = RenewWindow(batch=True, parent=self.parent()) dlg.exec_() def accept(self): if self.batch: self.slicesToRenew = self.sliceModel.getSelectedSlices() if self.slicesToRenew == []: QMessageBox.warning(self, "No Slices", "Please add at least on slice by double-clicking on a slice name") return else: self.slicesToRenew = [config.getSlice()] self.duration.setEnabled(False) self.buttonBox.setEnabled(False) if self.batch: self.sliceView.setEnabled(False) self.renewNextSlice() def setStatus(self, x): self.status.setText(x) def renewNextSlice(self): self.sliceName = self.slicesToRenew.pop(0) self.renewProcess = SfiRenewer(self.sliceName, self.get_new_expiration(), self) self.connect(self.renewProcess, SIGNAL('finished()'), self.renewFinished) self.setStatus("Renewing: %s." % self.sliceName) def renewFinished(self): self.disconnect(self.renewProcess, SIGNAL('finished()'), self.renewFinished) faultString = self.renewProcess.getFaultString() if faultString: self.setStatus("Renew %s Error: %s" % (self.sliceName, faultString)) self.buttonBox.setEnabled(True) else: self.setStatus("Renew %s Success" % self.sliceName) if (self.slicesToRenew != []): self.renewNextSlice() else: # give the user the button self.buttonBox.clear() self.buttonBox.addButton(QDialogButtonBox.Close) self.buttonBox.setEnabled(True) def get_new_expiration(self): index = self.duration.currentIndex() return self.expirations[index] def refreshAuthority(self): self.process = SfiProcess(self) self.connect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished) self.process.listRecords(config.getAuthority(), None) self.setStatus("Refreshing slice list. This will take a moment...") def getAuthorityRecordFinished(self): self.disconnect(self.process, SIGNAL('finished()'), self.getAuthorityRecordFinished) faultString = self.process.getFaultString() if not faultString: self.setStatus("Slice list refreshed.") self.updateSliceView() else: self.setStatus("Authority rec refresh error: %s" % (faultString)) def updateSliceView(self): self.sliceModel.updateModel() self.sliceView.setModel(self.sliceModel) self.sliceView.resizeColumnToContents(0)