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()
70 def processStandardError(self):
71 print self.process.readAllStandardError()
73 def processFinished(self):
74 if self.process.exitStatus() == QProcess.CrashExit:
75 print self.readOutput()
76 print "Process exited with errors:",
77 err = self.process.error()
78 if err == QProcess.FailedToStart:
80 elif err == QProcess.Crashed:
82 elif err == QProcess.Timedout:
84 elif err == QProcess.WriteError:
86 elif err == QProcess.ReadError:
88 elif err == QProcess.UnknownError:
91 self.emit(SIGNAL("finished()"))
93 def __getRSpec(self, mgr):
94 slice = config.getSlice()
95 # Write RSpec to file for testing.
96 filename = os.path.expanduser("~/.sfi/" + slice + ".rspec")
101 args = ["-u", config.getUser(), "-a", config.getAuthority(),
102 "-r", config.getRegistry(), "-s", mgr, "resources",
103 "-o", filename, slice]
105 self.__init_command(args)
109 def getRSpecFromSM(self):
110 return self.__getRSpec(config.getSlicemgr())
112 def getRSpecFromAM(self):
113 return self.__getRSpec(config.getAggmgr())
115 def getRecord(self, hrn):
116 args = ["-u", config.getUser(), "-a", config.getAuthority(),
117 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "show", hrn]
118 self.__init_command(args)
121 def applyRSpec(self, rspec):
122 filename = config.getSliceRSpecFile() + "_new"
124 args = ["-u", config.getUser(), "-a", config.getAuthority(),
125 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "create",
126 config.getSlice(), filename]
127 self.__init_command(args)
133 self.process.start(self.exe, self.args)
135 def readOutput(self):
136 if self.process.state() == QProcess.NotRunning:
137 return self.process.readAll()
139 def trace_command (self):
141 self._trace=time.time()
142 command = "%s %s" % (self.exe, self.args.join(" "))
143 print time.strftime('%M:%S'),'Invoking',command
145 def trace_end (self):
147 command = "%s %s" % (self.exe, self.args.join(" "))
148 print time.strftime('%M:%S'),"[%.3f s]"%(time.time()-self._trace),command,'Done'
149 self.xmltracker.getAndPrint(self.output)
153 self.xmlrpcWindow = XmlrpcWindow()
155 def getAndPrint(self, rawOutput):
156 self.store(rawOutput)
158 self.xmlrpcWindow.setData(self.xml)
161 def showXmlrpc(self):
162 self.xmlrpcWindow.show()
163 self.xmlrpcWindow.resize(500, 640)
164 self.xmlrpcWindow.raise_()
165 self.xmlrpcWindow.activateWindow()
167 def store(self, rawOutput):
168 self.rawOutput = rawOutput
170 def extractXml(self):
171 pttrnAsk = '<methodCall>.*?</methodCall>'
172 pttrnAns = '<methodResponse>.*?</methodResponse>'
173 answers = re.compile(pttrnAsk, re.DOTALL).findall(self.rawOutput)
174 replies = re.compile(pttrnAns, re.DOTALL).findall(self.rawOutput)
176 answers = map(lambda x: x.replace('\\n','\n'), answers)
177 replies = map(lambda x: x.replace('\\n','\n').replace("'\nbody: '", ''), replies)
178 replies.reverse() # so that I use pop() as popleft
179 # A well-formed XML document must have one, and only one, top-level element
182 self.xml += ans + replies.pop()
183 self.xml += '</debug>'
186 # statistics: round-trip time, size of the com
189 def prettyPrint(self, XmlComs):
193 class XmlrpcWindow(RSpecWindow):
194 def __init__(self, parent=None):
195 # super __init__() calls updateView,
196 # which assumes you have some data
197 self.data = '<debug/>'
198 RSpecWindow.__init__(self, parent)
200 def setData(self, XmlrpcCom):
201 self.data = XmlrpcCom
203 def updateView(self):
209 self.document = QDomDocument("RSpec")
210 self.document.setContent(self.data)
211 self.model = DomModel(self.document, self)
213 self.view.setModel(self.model)
214 self.view.expand(self.model.index(0, 0)) #expand first level only