9 from PyQt4.QtCore import *
10 from sface.config import config
11 from sface.xmlrpcwindow import get_tracker, XmlrpcReader
13 def find_executable(exec_name):
14 """find the given executable in $PATH"""
15 paths = os.getenv("PATH").split(':')
17 exec_path = os.path.join(p, exec_name)
18 if os.path.exists(exec_path) and os.access(exec_path,os.X_OK):
23 class SfiProcess(QObject):
24 def __init__(self, parent=None):
25 QObject.__init__(self, parent)
27 env = QProcess.systemEnvironment()
28 env << "PYTHONPATH=%s" % ":".join(sys.path)
29 self.process = QProcess()
30 self.process.setEnvironment(env)
31 self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"),
34 self.xmlrpcreader = XmlrpcReader() # this one is for parsing XMLRPC responses
36 # holds aggregate output from processStandardOutput(); used by xmlrpc
40 self.do_raw = True # xxx should check version of sfa
42 self.connect(self.process, SIGNAL("readyReadStandardOutput()"),
43 self.processStandardOutput)
44 self.connect(self.process, SIGNAL("readyReadStandardError()"),
45 self.processStandardError)
47 def __init_command(self, args, save_filename=None):
48 self.args = QStringList()
50 self.args << config.get_dirname()
52 # this shows xmlrpc conversation, see sfi.py docs.
53 # always do this, so we can parse the XML result for faults and show
55 self.args << QString('-D')
58 self.raw_filename = tempfile.mktemp(suffix=".raw")
59 self.args << QString('-R')
60 self.args << QString(self.raw_filename)
61 self.args << QString('--rawformat')
62 self.args << QString('json')
64 self.raw_filename = None
66 self.save_filename = save_filename
69 self.args << QString(arg)
71 self.exe = find_executable("sfi.py")
73 print "FATAL.. Could not locate binary sfi.py - not much we can do without that"
76 return self.process.state() != QProcess.NotRunning
78 def processStandardOutput(self):
79 output = self.process.readAllStandardOutput()
80 self.output = self.output + output
86 # XXX why is this happening??
87 print "*** caught EINTR"
92 def processStandardError(self):
93 print self.process.readAllStandardError()
95 def processFinished(self):
96 if self.process.exitStatus() == QProcess.CrashExit:
97 print self.readOutput()
98 print "Process exited with errors:",
99 err = self.process.error()
100 if err == QProcess.FailedToStart:
101 print "FailedToStart"
102 elif err == QProcess.Crashed:
104 elif err == QProcess.Timedout:
106 elif err == QProcess.WriteError:
108 elif err == QProcess.ReadError:
110 elif err == QProcess.UnknownError:
114 if (self.raw_filename != None) and os.path.exists(self.raw_filename):
115 if hasattr(json, "loads"):
116 self.raw_data = json.loads(open(self.raw_filename,"r").read()) # python 2.6
118 self.raw_data = json.read(open(self.raw_filename,"r").read()) # python 2.5
120 os.remove(self.raw_filename)
123 self.geni_output=None
124 if (self.raw_data!=None) and (type(self.raw_data)==dict):
125 code = self.raw_data.get("code",{})
126 self.geni_code = code.get("geni_code",None)
127 self.geni_output = self.raw_data.get("output","")
129 if self.save_filename:
130 value = self.raw_data.get("value", None)
132 if os.path.exists(self.save_filename):
133 os.remove(self.save_filename)
134 elif type(value) == str:
135 open(self.save_filename, "w").write(value)
136 elif hasattr(json, "dumps"):
137 open(self.save_filename, "w").write(json.dumps(value)) # python 2.6
139 open(self.save_filename, "w").write(json.write(value)) # python 2.5
141 # extract any faults from the XMLRPC response(s)
142 self.xmlrpcreader.responses = []
143 self.xmlrpcreader.store(self.output)
144 self.xmlrpcreader.extractXml()
145 self.responses = self.xmlrpcreader.responses
146 self.faults = [x for x in self.responses if (x["kind"]=="fault")]
148 # if we got a nonzero
149 if (self.geni_code!=None) and (self.geni_code!=0):
150 x = {"kind": "bad_geni_code"}
151 x["faultCode"] = str(self.geni_code)
152 faultString = "Nonzero geni_code: " + str(self.geni_code)
154 faultString = faultString + " output: " + str(self.geni_output)
155 x["faultString"] = faultString
156 self.faults.append(x)
159 self.emit(SIGNAL("finished()"))
161 def getFaultString(self):
162 if self.faults == []:
165 return self.faults[0].get("faultString","") + " (" + self.faults[0].get("faultCode","") + ")"
167 def retrieveRspec(self):
168 slice = config.getSlice()
169 mgr = config.getSlicemgr()
170 # Write RSpec to file
171 filename = config.fullpath ("%s.rspec"%slice)
176 args = ["-u", config.getUser(), "-a", config.getAuthority(),
177 "-r", config.getRegistry(), "-s", mgr, "resources",
178 "-o", filename, slice]
180 self.__init_command(args)
184 def retrieveResources(self):
185 mgr = config.getSlicemgr()
186 # Write RSpec to file
187 filename = config.getResourcesRSpecFile()
192 args = ["-u", config.getUser(), "-a", config.getAuthority(),
193 "-r", config.getRegistry(), "-s", mgr, "resources",
196 self.__init_command(args)
201 def listRecords(self, hrn, rectype=None, filename=None):
202 args = ["-u", config.getUser(), "-a", config.getAuthority(),
203 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "list", "-F", "xmllist", hrn]
206 filename = config.getAuthorityListFile()
208 # we can't tell whether SFI will create one file or many, so delete
209 # leftovers from last time, then we'll know what we got, after we get it.
210 if os.path.exists(filename):
212 if os.path.exists(filename + ".1"):
213 os.remove(filename + ".1")
215 args.append(filename)
221 self.__init_command(args)
224 def getRecord(self, hrn, type=None, filename=None):
225 args = ["-u", config.getUser(),
226 "-a", config.getAuthority(),
227 "-r", config.getRegistry(),
228 "-s", config.getSlicemgr(),
235 args.append(filename)
236 self.__init_command(args)
239 def getSliceRecord(self):
240 self.getRecord(config.getSlice(), type="slice", filename=config.getSliceRecordFile())
242 def getAuthorityRecord(self):
243 self.getRecord(config.getAuthority(), filename=config.getAuthorityRecordFile())
245 def applyRSpec(self, rspec, aggAddr=None, aggPort=None, saveObtained=True):
246 # that's what we pass, like in what we'd like to get
247 requested = config.getSliceRSpecFile() + "_new"
248 # that's what we actually receive
249 # just overwrite the slice file as if we'd used 'resources'
250 obtained = config.getSliceRSpecFile()
251 rspec.save(requested)
252 args = ["-u", config.getUser(), "-a", config.getAuthority(),
253 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "create"]
256 args = args + ["-o", obtained]
259 args = args + ["-a", aggAddr, "-p", str(aggPort)]
261 args = args + [config.getSlice(), requested]
263 self.__init_command(args)
266 def deleteSlivers(self, slice=None, aggAddr=None, aggPort=None):
268 slice = config.getSlice()
270 args = ["-u", config.getUser(), "-a", config.getAuthority(),
271 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "delete"]
274 args = args + ["-a", aggAddr, "-p", str(aggPort)]
276 args = args + [slice]
278 self.__init_command(args)
281 def updateRecord(self, filename):
282 args = ["-u", config.getUser(), "-a", config.getAuthority(),
283 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "update", filename]
284 self.__init_command(args)
287 def addRecord(self, filename):
288 args = ["-u", config.getUser(), "-a", config.getAuthority(),
289 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "add", filename]
290 self.__init_command(args)
293 def removeRecord(self, hrn):
294 args = ["-u", config.getUser(), "-a", config.getAuthority(),
295 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "remove", hrn]
296 self.__init_command(args)
299 def renewSlivers(self, expiration, slice=None):
301 slice = config.getSlice()
303 args = ["-u", config.getUser(), "-a", config.getAuthority(),
304 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "renew",
306 self.__init_command(args)
309 def sliverStatus(self, slice=None, filename=None):
311 slice = config.getSlice()
314 filename = config.fullpath(slice+".sliverstatus")
316 args = ["-u", config.getUser(), "-a", config.getAuthority(),
317 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "status",
319 self.__init_command(args, save_filename = filename)
322 def getSliceMgrVersion(self, filename=None):
324 filename = config.fullpath("slicemgr.version")
326 args = ["-u", config.getUser(), "-a", config.getAuthority(),
327 "-r", config.getRegistry(), "-s", config.getSlicemgr(), "version",
328 "-o", filename, "-F", "pickled",]
329 self.__init_command(args)
337 self.process.start(self.exe, self.args)
339 def readOutput(self):
340 if self.process.state() == QProcess.NotRunning:
341 return self.process.readAll()
343 def trace_command (self):
345 self._trace=time.time()
346 command = "%s %s" % (self.exe, self.args.join(" "))
347 print time.strftime('%H:%M:%S'),'Invoking',command
349 def trace_end (self):
351 # command = "%s %s" % (self.exe, self.args.join(" "))
352 print time.strftime('%H:%M:%S'),"Done [%.3f s]"%(time.time()-self._trace)
354 get_tracker().getAndPrint(self.output)