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)