7 from PyQt4.QtCore import *
8 from PyQt4.QtXml import QDomDocument
9 from sface.config import config
10 from sface.logwindow import LogIO
11 from sface.rspecwindow import RSpecWindow, DomModel
14 def find_executable(exec_name):
15 """find the given executable in $PATH"""
16 paths = os.getenv("PATH").split(':')
18 exec_path = os.path.join(p, exec_name)
19 if os.path.exists(exec_path):
24 class SfiProcess(QObject):
25 def __init__(self, parent=None):
26 QObject.__init__(self, parent)
28 self.process = QProcess()
29 self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"),
32 self.xmltracker = XmlTracker()
33 # in case self.output is read by the XmlTracker before any
34 # readyReadStandardOutput signal
37 self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
38 self.processStandardOutput)
39 self.connect(self.process, SIGNAL("readyReadStandardError()"),
40 self.processStandardError)
42 def __init_command(self, args):
43 self.args = QStringList()
45 # this shows xmlrpc conversation, see sfi.py docs.
46 self.args << QString('-D')
48 self.args << QString(arg)
50 self.exe = find_executable("sfi.py")
52 print "FATAL.. Could not locate binary sfi.py - not much we can do without that"
55 return self.process.state() != QProcess.NotRunning
57 def processStandardOutput(self):
58 # NOTE: The signal readyReadStandardOutput is emitted when
59 # the process has made new data available through its standard output channel.
60 # But the process is not necessarily finished.
61 # It's cool to have this method wo we print the stdOut live,
62 # but we must be carefull with self.output, used by xmlTracker too.
63 print "SETTING SELF.OUTPUT"
64 tmpOut = self.process.readAllStandardOutput()
69 def processStandardError(self):
70 print self.process.readAllStandardError()
72 def processFinished(self):
73 if self.process.exitStatus() == QProcess.CrashExit:
74 print self.readOutput()
75 print "Process exited with errors:",
76 err = self.process.error()
77 if err == QProcess.FailedToStart:
79 elif err == QProcess.Crashed:
81 elif err == QProcess.Timedout:
83 elif err == QProcess.WriteError:
85 elif err == QProcess.ReadError:
87 elif err == QProcess.UnknownError:
90 self.emit(SIGNAL("finished()"))
92 def __getRSpec(self, mgr):
93 slice = config.getSlice()
94 # Write RSpec to file for testing.
95 filename = os.path.expanduser("~/.sfi/" + slice + ".rspec")
100 args = ["-u", config.getUser(), "-a", config.getAuthority(),
101 "-r", config.getRegistry(), "-s", mgr, "resources",
102 "-o", filename, slice]
104 self.__init_command(args)
108 def getRSpecFromSM(self):
109 return self.__getRSpec(config.getSlicemgr())
111 def getRSpecFromAM(self):
112 return self.__getRSpec(config.getAggmgr())
114 def getRecord(self, hrn):
115 args = ["-u", config.getUser(), "-a", config.getAuthority(),
116 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "show", hrn]
117 self.__init_command(args)
120 def applyRSpec(self, rspec):
121 filename = config.getSliceRSpecFile() + "_new"
123 args = ["-u", config.getUser(), "-a", config.getAuthority(),
124 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "create",
125 config.getSlice(), filename]
126 self.__init_command(args)
132 self.process.start(self.exe, self.args)
134 def readOutput(self):
135 if self.process.state() == QProcess.NotRunning:
136 return self.process.readAll()
138 def trace_command (self):
140 self._trace=time.time()
141 command = "%s %s" % (self.exe, self.args.join(" "))
142 print time.strftime('%M:%S'),'Invoking',command
144 def trace_end (self):
146 command = "%s %s" % (self.exe, self.args.join(" "))
147 print time.strftime('%M:%S'),"[%.3f s]"%(time.time()-self._trace),command,'Done'
148 self.xmltracker.getAndPrint(self.output)
152 self.xmlrpcWindow = XmlrpcWindow()
154 def getAndPrint(self, rawOutput):
155 self.store(rawOutput)
157 self.xmlrpcWindow.setData(self.xml)
160 def showXmlrpc(self):
161 self.xmlrpcWindow.show()
162 self.xmlrpcWindow.resize(500, 640)
163 self.xmlrpcWindow.raise_()
164 self.xmlrpcWindow.activateWindow()
166 def store(self, rawOutput):
167 self.rawOutput = rawOutput
169 def extractXml(self):
170 pttrnAsk = '<methodCall>.*?</methodCall>'
171 pttrnAns = '<methodResponse>.*?</methodResponse>'
172 answers = re.compile(pttrnAsk, re.DOTALL).findall(self.rawOutput)
173 replies = re.compile(pttrnAns, re.DOTALL).findall(self.rawOutput)
175 answers = map(lambda x: x.replace('\\n','\n'), answers)
176 replies = map(lambda x: x.replace('\\n','\n').replace("'\nbody: '", ''), replies)
177 replies.reverse() # so that I use pop() as popleft
178 # A well-formed XML document must have one, and only one, top-level element
181 self.xml += ans + replies.pop()
182 self.xml += '</debug>'
185 # statistics: round-trip time, size of the com
188 def prettyPrint(self, XmlComs):
192 class XmlrpcWindow(RSpecWindow):
193 def __init__(self, parent=None):
194 # super __init__() calls updateView,
195 # which assumes you have some data
196 self.data = '<debug/>'
197 RSpecWindow.__init__(self, parent)
199 def setData(self, XmlrpcCom):
200 self.data = XmlrpcCom
202 def updateView(self):
208 self.document = QDomDocument("RSpec")
209 self.document.setContent(self.data)
210 self.model = DomModel(self.document, self)
212 self.view.setModel(self.model)
213 self.view.expand(self.model.index(0, 0)) #expand first level only