xref: /onnv-gate/usr/src/tools/onbld/Checks/DbLookups.py (revision 8174:29be171fb93b)
17078Smjnelson#! /usr/bin/python
27078Smjnelson#
37078Smjnelson# CDDL HEADER START
47078Smjnelson#
57078Smjnelson# The contents of this file are subject to the terms of the
67078Smjnelson# Common Development and Distribution License (the "License").
77078Smjnelson# You may not use this file except in compliance with the License.
87078Smjnelson#
97078Smjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107078Smjnelson# or http://www.opensolaris.org/os/licensing.
117078Smjnelson# See the License for the specific language governing permissions
127078Smjnelson# and limitations under the License.
137078Smjnelson#
147078Smjnelson# When distributing Covered Code, include this CDDL HEADER in each
157078Smjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167078Smjnelson# If applicable, add the following below this CDDL HEADER, with the
177078Smjnelson# fields enclosed by brackets "[]" replaced with your own identifying
187078Smjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
197078Smjnelson#
207078Smjnelson# CDDL HEADER END
217078Smjnelson#
227078Smjnelson
237078Smjnelson#
247078Smjnelson# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
257078Smjnelson# Use is subject to license terms.
267078Smjnelson#
277078Smjnelson
287078Smjnelson#
297078Smjnelson# Various database lookup classes/methods, i.e.:
307078Smjnelson#     * monaco
317078Smjnelson#     * bugs.opensolaris.org (b.o.o.)
327078Smjnelson#     * opensolaris.org/cgi/arc.py (for ARC)
337078Smjnelson#
347078Smjnelson
357078Smjnelsonimport re
367078Smjnelsonimport urllib
378042SJohn.Sonnenschein@Sun.COMimport urllib2
387078Smjnelsonimport htmllib
397078Smjnelsonimport os
407078Smjnelsonfrom socket import socket, AF_INET, SOCK_STREAM
417078Smjnelson
427078Smjnelsonfrom onbld.Checks import onSWAN
437078Smjnelson
447078Smjnelsonclass BugException(Exception):
457078Smjnelson	def __init__(self, data=''):
467078Smjnelson		self.data = data
477078Smjnelson		Exception.__init__(self, data)
487078Smjnelson
497078Smjnelson	def __str__(self):
507078Smjnelson		return "Unknown error: %s" % self.data
517078Smjnelson
527078Smjnelsonclass NonExistentBug(BugException):
537078Smjnelson	def __str__(self):
547078Smjnelson		return "Bug %s does not exist" % self.data
557078Smjnelson
568042SJohn.Sonnenschein@Sun.COMclass BugDBException(Exception):
578042SJohn.Sonnenschein@Sun.COM	def __init__(self, data=''):
588042SJohn.Sonnenschein@Sun.COM		self.data = data
598042SJohn.Sonnenschein@Sun.COM		Exception.__init__(self, data)
607078Smjnelson
618042SJohn.Sonnenschein@Sun.COM	def __str__(self):
628042SJohn.Sonnenschein@Sun.COM		return "Unknown bug database: %s" % self.data
637078Smjnelson
647078Smjnelsonclass BugDB(object):
657078Smjnelson	"""Lookup change requests.
667078Smjnelson
677078Smjnelson	Object can be used on or off of SWAN, using either monaco or
687078Smjnelson	bugs.opensolaris.org as a database.
697078Smjnelson
707078Smjnelson	Usage:
717078Smjnelson	bdb = BugDB()
727078Smjnelson	r = bdb.lookup("6455550")
737078Smjnelson	print r["6455550"]["synopsis"]
747078Smjnelson	r = bdb.lookup(["6455550", "6505625"])
757078Smjnelson	print r["6505625"]["synopsis"]
767078Smjnelson	"""
777078Smjnelson
788042SJohn.Sonnenschein@Sun.COM	def __init__(self, priority = ("bugster",), forceBoo = False):
797078Smjnelson		"""Create a BugDB object.
807078Smjnelson
817078Smjnelson		Keyword argument:
827078Smjnelson		forceBoo: use b.o.o even from SWAN (default=False)
838042SJohn.Sonnenschein@Sun.COM		priority: use bug databases in this order
847078Smjnelson		"""
858042SJohn.Sonnenschein@Sun.COM		self.__validBugDB = ["bugster"]
868042SJohn.Sonnenschein@Sun.COM		self.__onSWAN = not forceBoo and onSWAN()
878042SJohn.Sonnenschein@Sun.COM		for database in priority:
888042SJohn.Sonnenschein@Sun.COM			if database not in self.__validBugDB:
898042SJohn.Sonnenschein@Sun.COM				raise BugDBException, database
908042SJohn.Sonnenschein@Sun.COM		self.__priority = priority
918042SJohn.Sonnenschein@Sun.COM
928042SJohn.Sonnenschein@Sun.COM
938042SJohn.Sonnenschein@Sun.COM	def __boobug(self, cr):
948042SJohn.Sonnenschein@Sun.COM		cr = str(cr)
958042SJohn.Sonnenschein@Sun.COM		url = "http://bugs.opensolaris.org/view_bug.do"
968042SJohn.Sonnenschein@Sun.COM   		req = urllib2.Request(url, urllib.urlencode({"bug_id": cr}))
978042SJohn.Sonnenschein@Sun.COM		results = {}
988042SJohn.Sonnenschein@Sun.COM		try:
998042SJohn.Sonnenschein@Sun.COM			data = urllib2.urlopen(req).readlines()
1008042SJohn.Sonnenschein@Sun.COM		except urllib2.HTTPError, e:
1018042SJohn.Sonnenschein@Sun.COM			if e.code != 404:
1028042SJohn.Sonnenschein@Sun.COM				print "ERROR: HTTP error at " + \
1038042SJohn.Sonnenschein@Sun.COM					req.get_full_url() + \
1048042SJohn.Sonnenschein@Sun.COM					" got error: " + str(e.code)
1058042SJohn.Sonnenschein@Sun.COM				raise e
1068042SJohn.Sonnenschein@Sun.COM			else:
1078042SJohn.Sonnenschein@Sun.COM				raise NonExistentBug
1088042SJohn.Sonnenschein@Sun.COM		except urllib2.URLError, e:
1098042SJohn.Sonnenschein@Sun.COM			print "ERROR: could not connect to " + \
1108042SJohn.Sonnenschein@Sun.COM				req.get_full_url() + \
1118042SJohn.Sonnenschein@Sun.COM				' got error: "' + e.reason[1] + '"'
1128042SJohn.Sonnenschein@Sun.COM			raise e
1138042SJohn.Sonnenschein@Sun.COM		htmlParser = htmllib.HTMLParser(None)
1148042SJohn.Sonnenschein@Sun.COM		metaHtmlRe = re.compile(r'^<meta name="([^"]+)" content="([^"]*)">$')
1158042SJohn.Sonnenschein@Sun.COM		for line in data:
1168042SJohn.Sonnenschein@Sun.COM			m = metaHtmlRe.search(line)
1178042SJohn.Sonnenschein@Sun.COM			if not m:
1188042SJohn.Sonnenschein@Sun.COM				continue
1198042SJohn.Sonnenschein@Sun.COM			val = urllib.unquote(m.group(2))
1208042SJohn.Sonnenschein@Sun.COM			htmlParser.save_bgn()
1218042SJohn.Sonnenschein@Sun.COM			htmlParser.feed(val)
1228042SJohn.Sonnenschein@Sun.COM			results[m.group(1)] = htmlParser.save_end()
1238042SJohn.Sonnenschein@Sun.COM		htmlParser.close()
1248042SJohn.Sonnenschein@Sun.COM
1258042SJohn.Sonnenschein@Sun.COM		if "synopsis" not in results:
1268042SJohn.Sonnenschein@Sun.COM			raise NonExistentBug(cr)
1278042SJohn.Sonnenschein@Sun.COM
1288042SJohn.Sonnenschein@Sun.COM		results["cr_number"] = cr
1298042SJohn.Sonnenschein@Sun.COM		results["sub_category"] = results.pop("subcategory")
1308042SJohn.Sonnenschein@Sun.COM		results["status"] = results.pop("state")
1318042SJohn.Sonnenschein@Sun.COM		results["date_submitted"] = results.pop("submit_date")
1328042SJohn.Sonnenschein@Sun.COM
1338042SJohn.Sonnenschein@Sun.COM		return results
1348042SJohn.Sonnenschein@Sun.COM
1358042SJohn.Sonnenschein@Sun.COM
1368042SJohn.Sonnenschein@Sun.COM	def __monaco(self, crs):
1378042SJohn.Sonnenschein@Sun.COM		"""Return all info for requested change reports.
1388042SJohn.Sonnenschein@Sun.COM
1398042SJohn.Sonnenschein@Sun.COM		Argument:
1408042SJohn.Sonnenschein@Sun.COM		crs: list of change request ids
1418042SJohn.Sonnenschein@Sun.COM
1428042SJohn.Sonnenschein@Sun.COM		Returns:
1438042SJohn.Sonnenschein@Sun.COM		Dictionary, mapping CR=>dictionary, where the nested dictionary
1448042SJohn.Sonnenschein@Sun.COM		is a mapping of field=>value
1458042SJohn.Sonnenschein@Sun.COM		"""
1468042SJohn.Sonnenschein@Sun.COM
1478042SJohn.Sonnenschein@Sun.COM		#
1488042SJohn.Sonnenschein@Sun.COM		# We request synopsis last, and split on only
1498042SJohn.Sonnenschein@Sun.COM		# the number of separators that we expect to
1508042SJohn.Sonnenschein@Sun.COM		# see such that a | in the synopsis doesn't
1518042SJohn.Sonnenschein@Sun.COM		# throw us out of whack.
1528042SJohn.Sonnenschein@Sun.COM		#
1538042SJohn.Sonnenschein@Sun.COM		monacoFields = [ "cr_number", "category", "sub_category",
1548042SJohn.Sonnenschein@Sun.COM			"area", "release", "build", "responsible_manager",
1558042SJohn.Sonnenschein@Sun.COM			"responsible_engineer", "priority", "status", "sub_status",
1568042SJohn.Sonnenschein@Sun.COM			"submitted_by", "date_submitted", "synopsis" ]
1578042SJohn.Sonnenschein@Sun.COM		cmd = []
1588042SJohn.Sonnenschein@Sun.COM		cmd.append("set What = cr." + ', cr.'.join(monacoFields))
1598042SJohn.Sonnenschein@Sun.COM		cmd.append("")
1608042SJohn.Sonnenschein@Sun.COM		cmd.append("set Which = cr.cr_number in (" + ','.join(crs) +")")
1618042SJohn.Sonnenschein@Sun.COM		cmd.append("")
1628042SJohn.Sonnenschein@Sun.COM		cmd.append("set FinalClauses = order by cr.cr_number")
1638042SJohn.Sonnenschein@Sun.COM		cmd.append("")
1648042SJohn.Sonnenschein@Sun.COM		cmd.append("doMeta genQuery cr")
1658042SJohn.Sonnenschein@Sun.COM		url = "http://hestia.sfbay.sun.com/cgi-bin/expert?format="
1668042SJohn.Sonnenschein@Sun.COM		url += "Pipe-delimited+text;Go=2;no_header=on;cmds="
1678042SJohn.Sonnenschein@Sun.COM		url += urllib.quote_plus("\n".join(cmd))
1688042SJohn.Sonnenschein@Sun.COM		results = {}
1698042SJohn.Sonnenschein@Sun.COM		try:
1708042SJohn.Sonnenschein@Sun.COM			data = urllib2.urlopen(url).readlines()
1718042SJohn.Sonnenschein@Sun.COM		except urllib2.HTTPError, e:
1728042SJohn.Sonnenschein@Sun.COM			print "ERROR: HTTP error at " + url + \
1738042SJohn.Sonnenschein@Sun.COM				" got error: " + str(e.code)
1748042SJohn.Sonnenschein@Sun.COM			raise e
1758042SJohn.Sonnenschein@Sun.COM
1768042SJohn.Sonnenschein@Sun.COM		except urllib2.URLError, e:
1778042SJohn.Sonnenschein@Sun.COM			print "ERROR: could not connect to " + url + \
1788042SJohn.Sonnenschein@Sun.COM				' got error: "' + e.reason[1] + '"'
1798042SJohn.Sonnenschein@Sun.COM			raise e
1808042SJohn.Sonnenschein@Sun.COM		for line in data:
1818042SJohn.Sonnenschein@Sun.COM			line = line.rstrip('\n')
1828042SJohn.Sonnenschein@Sun.COM			values = line.split('|', len(monacoFields) - 1)
1838042SJohn.Sonnenschein@Sun.COM			v = 0
1848042SJohn.Sonnenschein@Sun.COM			cr = values[0]
1858042SJohn.Sonnenschein@Sun.COM			results[cr] = {}
1868042SJohn.Sonnenschein@Sun.COM			for field in monacoFields:
1878042SJohn.Sonnenschein@Sun.COM				results[cr][field] = values[v]
1888042SJohn.Sonnenschein@Sun.COM				v += 1
1898042SJohn.Sonnenschein@Sun.COM		return results
1907078Smjnelson
1917078Smjnelson	def lookup(self, crs):
1927078Smjnelson		"""Return all info for requested change reports.
1937078Smjnelson
1947078Smjnelson		Argument:
1957078Smjnelson		crs: one change request id (may be integer, string, or list),
1967078Smjnelson	             or multiple change request ids (must be a list)
1977078Smjnelson
1987078Smjnelson		Returns:
1997078Smjnelson		Dictionary, mapping CR=>dictionary, where the nested dictionary
2007078Smjnelson		is a mapping of field=>value
2017078Smjnelson		"""
2028042SJohn.Sonnenschein@Sun.COM		results = {}
2037078Smjnelson		if not isinstance(crs, list):
2047078Smjnelson			crs = [str(crs)]
2058042SJohn.Sonnenschein@Sun.COM		for database in self.__priority:
2068042SJohn.Sonnenschein@Sun.COM			if database == "bugster":
2078042SJohn.Sonnenschein@Sun.COM				if self.__onSWAN:
2088042SJohn.Sonnenschein@Sun.COM					results.update(self.__monaco(crs))
2098042SJohn.Sonnenschein@Sun.COM				# else we're off-swan and querying via boo, which we can
2108042SJohn.Sonnenschein@Sun.COM				# only do one bug at a time
2118042SJohn.Sonnenschein@Sun.COM				else:
2128042SJohn.Sonnenschein@Sun.COM					for cr in crs:
2138042SJohn.Sonnenschein@Sun.COM						cr = str(cr)
2148042SJohn.Sonnenschein@Sun.COM						try:
2158042SJohn.Sonnenschein@Sun.COM							results[cr] = self.__boobug(cr)
2168042SJohn.Sonnenschein@Sun.COM						except NonExistentBug:
2178042SJohn.Sonnenschein@Sun.COM							continue
2187078Smjnelson
2198042SJohn.Sonnenschein@Sun.COM			# the CR has already been found by one bug database
2208042SJohn.Sonnenschein@Sun.COM			# so don't bother looking it up in the others
2218042SJohn.Sonnenschein@Sun.COM			for cr in crs:
2228042SJohn.Sonnenschein@Sun.COM				if cr in results:
2238042SJohn.Sonnenschein@Sun.COM					crs.remove(cr)
2248042SJohn.Sonnenschein@Sun.COM
2258042SJohn.Sonnenschein@Sun.COM		return results
2268042SJohn.Sonnenschein@Sun.COM####################################################################
2278042SJohn.Sonnenschein@Sun.COMdef ARC(arclist):
2288042SJohn.Sonnenschein@Sun.COM	opts = {}
2298042SJohn.Sonnenschein@Sun.COM	url = "http://opensolaris.org/cgi/arc.py"
2308042SJohn.Sonnenschein@Sun.COM	opts["n"] = str(len(arclist))
2318042SJohn.Sonnenschein@Sun.COM	for i, arc in enumerate(arclist):
2328042SJohn.Sonnenschein@Sun.COM		arc, case = arc
2338042SJohn.Sonnenschein@Sun.COM		opts["arc" + str(i)] = arc
2348042SJohn.Sonnenschein@Sun.COM		opts["case" + str(i)] = case
2358042SJohn.Sonnenschein@Sun.COM	req = urllib2.Request(url, urllib.urlencode(opts))
2368042SJohn.Sonnenschein@Sun.COM	try:
2378042SJohn.Sonnenschein@Sun.COM		data = urllib2.urlopen(req).readlines()
2388042SJohn.Sonnenschein@Sun.COM	except urllib2.HTTPError, e:
239*8174SJohn.Sonnenschein@Sun.COM		print "ERROR: HTTP error at " + req.get_full_url() + \
2408042SJohn.Sonnenschein@Sun.COM			" got error: " + str(e.code)
2418042SJohn.Sonnenschein@Sun.COM		raise e
2427078Smjnelson
2438042SJohn.Sonnenschein@Sun.COM	except urllib2.URLError, e:
244*8174SJohn.Sonnenschein@Sun.COM		print "ERROR: could not connect to " + req.get_full_url() + \
2458042SJohn.Sonnenschein@Sun.COM			' got error: "' + e.reason[1] + '"'
2468042SJohn.Sonnenschein@Sun.COM		raise e
2478042SJohn.Sonnenschein@Sun.COM	ret = {}
2488042SJohn.Sonnenschein@Sun.COM	for line in data:
2498042SJohn.Sonnenschein@Sun.COM		oneline = line.rstrip('\n')
2508042SJohn.Sonnenschein@Sun.COM		fields = oneline.split('|')
2518042SJohn.Sonnenschein@Sun.COM		# check if each is valid ( fields[0]::validity )
2528042SJohn.Sonnenschein@Sun.COM		if fields[0] != "0":
2538042SJohn.Sonnenschein@Sun.COM			continue
2548042SJohn.Sonnenschein@Sun.COM		arc, case = fields[1].split(" ")
2558042SJohn.Sonnenschein@Sun.COM		ret[(arc, case)] = fields[2]
2568042SJohn.Sonnenschein@Sun.COM	return ret
2577078Smjnelson
2587078Smjnelson####################################################################
2597078Smjnelson
2607078Smjnelson# Pointers to the webrti server hostname & port to use
2617078Smjnelson# Using it directly is probably not *officially* supported, so we'll
2627078Smjnelson# have a pointer to the official `webrticli` command line interface
2637078Smjnelson# if using a direct socket connection fails for some reason, so we
2647078Smjnelson# have a fallback
2657078SmjnelsonWEBRTI_HOST = 'webrti.sfbay.sun.com'
2667078SmjnelsonWEBRTI_PORT = 9188
2677764SJohn.Sonnenschein@Sun.COMWEBRTICLI = '/net/onnv.sfbay.sun.com/export/onnv-gate/public/bin/webrticli'
2687078Smjnelson
2697078Smjnelson
2707078Smjnelsonclass RtiException(Exception):
2717078Smjnelson	def __init__(self, data=''):
2727078Smjnelson		self.data = data
2737078Smjnelson		Exception.__init__(self, data)
2747078Smjnelson
2757078Smjnelson	def __str__(self):
2767078Smjnelson		return "Unknown error: %s" % self.data
2777078Smjnelson
2787078Smjnelsonclass RtiCallFailed(RtiException):
2797078Smjnelson	def __str__(self):
2807078Smjnelson		return "Unable to call webrti: %s" % self.data
2817078Smjnelson
2827078Smjnelsonclass RtiSystemProblem(RtiException):
2837078Smjnelson	def __str__(self):
2847078Smjnelson		return "RTI status cannot be determined: %s" % self.data
2857078Smjnelson
2867078Smjnelsonclass RtiIncorrectCR(RtiException):
2877078Smjnelson	def __str__(self):
2887078Smjnelson		return "Incorrect CR number specified: %s" % self.data
2897078Smjnelson
2907078Smjnelsonclass RtiNotFound(RtiException):
2917078Smjnelson	def __str__(self):
2927078Smjnelson		return "RTI not found: %s" % self.data
2937078Smjnelson
2947078Smjnelsonclass RtiNeedConsolidation(RtiException):
2957078Smjnelson	def __str__(self):
2967078Smjnelson		return "More than one consolidation has this CR: %s" % self.data
2977078Smjnelson
2987078Smjnelsonclass RtiBadGate(RtiException):
2997078Smjnelson	def __str__(self):
3007078Smjnelson		return "Incorrect gate name specified: %s" % self.data
3017078Smjnelson
3027078Smjnelsonclass RtiOffSwan(RtiException):
3037078Smjnelson	def __str__(self):
3047078Smjnelson		return "RTI status checks need SWAN access: %s" % self.data
3057078Smjnelson
3067078SmjnelsonWEBRTI_ERRORS = {
3077078Smjnelson	'1': RtiSystemProblem,
3087078Smjnelson	'2': RtiIncorrectCR,
3097078Smjnelson	'3': RtiNotFound,
3107078Smjnelson	'4': RtiNeedConsolidation,
3117078Smjnelson	'5': RtiBadGate,
3127078Smjnelson}
3137078Smjnelson
3147078Smjnelson# Our Rti object which we'll use to represent an Rti query
3157078Smjnelson# It's really just a wrapper around the Rti connection, and attempts
3167078Smjnelson# to establish a direct socket connection and query the webrti server
3177078Smjnelson# directly (thus avoiding a system/fork/exec call).  If it fails, it
3187078Smjnelson# falls back to the webrticli command line client.
3197078Smjnelson
3207078SmjnelsonreturnCodeRe = re.compile(r'.*RETURN_CODE=(\d+)')
3217078Smjnelsonclass Rti:
3227078Smjnelson	"""Lookup an RTI.
3237078Smjnelson
3247078Smjnelson	Usage:
3257078Smjnelson	r = Rti("6640538")
3267078Smjnelson	print r.rtiNumber();
3277078Smjnelson	"""
3287078Smjnelson
3297078Smjnelson	def __init__(self, cr, gate=None, consolidation=None):
3307078Smjnelson		"""Create an Rti object for the specified change request.
3317078Smjnelson
3327078Smjnelson		Argument:
3337078Smjnelson		cr: change request id
3347078Smjnelson
3357078Smjnelson		Keyword arguments, to limit scope of RTI search:
3367078Smjnelson		gate: path to gate workspace (default=None)
3377078Smjnelson		consolidation: consolidation name (default=None)
3387078Smjnelson		"""
3397078Smjnelson
3407078Smjnelson		bufSz = 1024
3417078Smjnelson		addr = (WEBRTI_HOST, WEBRTI_PORT)
3427078Smjnelson		# If the passed 'cr' was given as an int, then wrap it
3437078Smjnelson		# into a string to make our life easier
3447078Smjnelson		if isinstance(cr, int):
3457078Smjnelson			cr = str(cr)
3467078Smjnelson		self.__queryCr = cr
3477078Smjnelson		self.__queryGate = gate
3487078Smjnelson		self.__queryConsolidation = consolidation
3497078Smjnelson
3507764SJohn.Sonnenschein@Sun.COM		self.__webRtiOutput = []
3517764SJohn.Sonnenschein@Sun.COM		self.__mainCR = []
3527764SJohn.Sonnenschein@Sun.COM		self.__rtiNumber = []
3537764SJohn.Sonnenschein@Sun.COM		self.__consolidation = []
3547764SJohn.Sonnenschein@Sun.COM		self.__project = []
3557764SJohn.Sonnenschein@Sun.COM		self.__status = []
3567764SJohn.Sonnenschein@Sun.COM		self.__rtiType = []
3577078Smjnelson		try:
3587078Smjnelson			# try to use a direct connection to the
3597078Smjnelson			# webrti server first
3607078Smjnelson			sock = socket(AF_INET, SOCK_STREAM)
3617078Smjnelson			sock.connect(addr)
3627078Smjnelson			command = "WEBRTICLI/1.0\nRTIstatus\n%s\n" % cr
3637078Smjnelson			if consolidation:
3647078Smjnelson				command += "-c\n%s\n" % consolidation
3657078Smjnelson			if gate:
3667078Smjnelson				command += "-g\n%s\n" % gate
3677078Smjnelson			command += "\n"
3687078Smjnelson			sock.send(command)
3697078Smjnelson			dataList = []
3707078Smjnelson			# keep receiving data from the socket until the
3717078Smjnelson			# server closes the connection
3727078Smjnelson			stillReceiving = True
3737078Smjnelson			while stillReceiving:
3747078Smjnelson				dataPiece = sock.recv(bufSz)
3757078Smjnelson				if dataPiece:
3767078Smjnelson					dataList.append(dataPiece)
3777078Smjnelson				else:
3787078Smjnelson					stillReceiving = False
3797078Smjnelson			# create the lines, skipping the first
3807078Smjnelson			# ("WEBRTCLI/1.0\n")
3817078Smjnelson			data = '\n'.join(''.join(dataList).split('\n')[1:])
3827078Smjnelson		except:
3837078Smjnelson			if not onSWAN():
3847078Smjnelson				raise RtiOffSwan(cr)
3857078Smjnelson
3867078Smjnelson			if not os.path.exists(WEBRTICLI):
3877078Smjnelson				raise RtiCallFailed('not found')
3887078Smjnelson
3897078Smjnelson			# fallback to the "supported" webrticli interface
3907078Smjnelson			command = WEBRTICLI
3917078Smjnelson			if consolidation:
3927078Smjnelson				command += " -c " + consolidation
3937078Smjnelson			if gate:
3947078Smjnelson				command += " -g " + gate
3957078Smjnelson			command += " RTIstatus " + cr
3967078Smjnelson
3977078Smjnelson			try:
3987078Smjnelson				cliPipe = os.popen(command)
3997078Smjnelson			except:
4007078Smjnelson				# we couldn't call the webrticli for some
4017078Smjnelson				# reason, so return a failure
4027078Smjnelson				raise RtiCallFailed('unknown')
4037078Smjnelson
4047078Smjnelson			data = cliPipe.readline()
4057078Smjnelson
4067078Smjnelson		# parse the data to see if we got a return code
4077078Smjnelson		# if we did, then that's bad.  if we didn't,
4087078Smjnelson		# then our call was successfully
4097078Smjnelson		m = returnCodeRe.search(data)
4107078Smjnelson		if m:
4117078Smjnelson			# we got a return code, set it in our
4127078Smjnelson			# object, set the webRtiOutput for debugging
4137078Smjnelson			# or logging, and return a failure
4147078Smjnelson			if m.group(1) in WEBRTI_ERRORS:
4157078Smjnelson				exc = WEBRTI_ERRORS[m.group(1)]
4167078Smjnelson			else:
4177078Smjnelson				exc = RtiException
4187078Smjnelson			raise exc(data)
4197078Smjnelson
4207764SJohn.Sonnenschein@Sun.COM		data = data.splitlines()
4217078Smjnelson		# At this point, we should have valid data
4227764SJohn.Sonnenschein@Sun.COM		for line in data:
4237764SJohn.Sonnenschein@Sun.COM			line = line.rstrip('\r\n')
4247764SJohn.Sonnenschein@Sun.COM			self.__webRtiOutput.append(line)
4257764SJohn.Sonnenschein@Sun.COM			fields = line.split(':')
4267764SJohn.Sonnenschein@Sun.COM			self.__mainCR.append(fields[0])
4277764SJohn.Sonnenschein@Sun.COM			self.__rtiNumber.append(fields[1])
4287764SJohn.Sonnenschein@Sun.COM			self.__consolidation.append(fields[2])
4297764SJohn.Sonnenschein@Sun.COM			self.__project.append(fields[3])
4307764SJohn.Sonnenschein@Sun.COM			self.__status.append(fields[4])
4317764SJohn.Sonnenschein@Sun.COM			self.__rtiType.append(fields[5])
4327078Smjnelson
4337078Smjnelson	# accessors in case callers need the raw data
4347078Smjnelson	def mainCR(self):
4357078Smjnelson		return self.__mainCR
4367078Smjnelson	def rtiNumber(self):
4377078Smjnelson		return self.__rtiNumber
4387078Smjnelson	def consolidation(self):
4397078Smjnelson		return self.__consolidation
4407078Smjnelson	def project(self):
4417078Smjnelson		return self.__project
4427078Smjnelson	def status(self):
4437078Smjnelson		return self.__status
4447078Smjnelson	def rtiType(self):
4457078Smjnelson		return self.__rtiType
4467078Smjnelson	def queryCr(self):
4477078Smjnelson		return self.__queryCr
4487078Smjnelson	def queryGate(self):
4497078Smjnelson		return self.__queryGate
4507078Smjnelson	def queryConsolidation(self):
4517078Smjnelson		return self.__queryConsolidation
4527078Smjnelson
4537078Smjnelson	# in practice, most callers only care about the following
4547078Smjnelson	def accepted(self):
4557764SJohn.Sonnenschein@Sun.COM		for status in self.__status:
4567764SJohn.Sonnenschein@Sun.COM			if status != "S_ACCEPTED":
4577764SJohn.Sonnenschein@Sun.COM				return False
4587764SJohn.Sonnenschein@Sun.COM		return True
4597078Smjnelson
4607078Smjnelson	# for logging/debugging in case the caller wants the raw webrti output
4617078Smjnelson	def webRtiOutput(self):
4627078Smjnelson		return self.__webRtiOutput
4637078Smjnelson
464