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# 24*12481SMark.J.Nelson@Oracle.COM# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 257078Smjnelson# 267078Smjnelson 277078Smjnelson# 287078Smjnelson# Various database lookup classes/methods, i.e.: 297078Smjnelson# * monaco 307078Smjnelson# * bugs.opensolaris.org (b.o.o.) 31*12481SMark.J.Nelson@Oracle.COM# * arc.opensolaris.org/cgi-bin/arc.cgi (for ARC off SWAN) 32*12481SMark.J.Nelson@Oracle.COM# * candi.sfbay.sun.com/cgi-bin/arc.cgi (for ARC on SWAN) 337078Smjnelson# 347078Smjnelson 359920SMark.J.Nelson@Sun.COMimport csv 367078Smjnelsonimport re 377078Smjnelsonimport urllib 388042SJohn.Sonnenschein@Sun.COMimport urllib2 397078Smjnelsonimport htmllib 407078Smjnelsonimport os 417078Smjnelsonfrom socket import socket, AF_INET, SOCK_STREAM 427078Smjnelson 437078Smjnelsonfrom onbld.Checks import onSWAN 447078Smjnelson 459920SMark.J.Nelson@Sun.COMclass NonExistentBug(Exception): 467078Smjnelson def __str__(self): 479920SMark.J.Nelson@Sun.COM return "Bug %s does not exist" % (Exception.__str__(self)) 487078Smjnelson 498042SJohn.Sonnenschein@Sun.COMclass BugDBException(Exception): 508042SJohn.Sonnenschein@Sun.COM def __str__(self): 519920SMark.J.Nelson@Sun.COM return "Unknown bug database: %s" % (Exception.__str__(self)) 527078Smjnelson 537078Smjnelsonclass BugDB(object): 547078Smjnelson """Lookup change requests. 557078Smjnelson 567078Smjnelson Object can be used on or off of SWAN, using either monaco or 577078Smjnelson bugs.opensolaris.org as a database. 587078Smjnelson 597078Smjnelson Usage: 607078Smjnelson bdb = BugDB() 617078Smjnelson r = bdb.lookup("6455550") 627078Smjnelson print r["6455550"]["synopsis"] 637078Smjnelson r = bdb.lookup(["6455550", "6505625"]) 647078Smjnelson print r["6505625"]["synopsis"] 657078Smjnelson """ 667078Smjnelson 679920SMark.J.Nelson@Sun.COM def __init__(self, priority = ("bugster",), forceBoo=False): 687078Smjnelson """Create a BugDB object. 697078Smjnelson 707078Smjnelson Keyword argument: 717078Smjnelson forceBoo: use b.o.o even from SWAN (default=False) 728042SJohn.Sonnenschein@Sun.COM priority: use bug databases in this order 737078Smjnelson """ 748042SJohn.Sonnenschein@Sun.COM self.__validBugDB = ["bugster"] 758042SJohn.Sonnenschein@Sun.COM self.__onSWAN = not forceBoo and onSWAN() 768042SJohn.Sonnenschein@Sun.COM for database in priority: 778042SJohn.Sonnenschein@Sun.COM if database not in self.__validBugDB: 788042SJohn.Sonnenschein@Sun.COM raise BugDBException, database 798042SJohn.Sonnenschein@Sun.COM self.__priority = priority 808042SJohn.Sonnenschein@Sun.COM 818042SJohn.Sonnenschein@Sun.COM 828042SJohn.Sonnenschein@Sun.COM def __boobug(self, cr): 838042SJohn.Sonnenschein@Sun.COM cr = str(cr) 848042SJohn.Sonnenschein@Sun.COM url = "http://bugs.opensolaris.org/view_bug.do" 858042SJohn.Sonnenschein@Sun.COM req = urllib2.Request(url, urllib.urlencode({"bug_id": cr})) 868042SJohn.Sonnenschein@Sun.COM results = {} 878042SJohn.Sonnenschein@Sun.COM try: 888042SJohn.Sonnenschein@Sun.COM data = urllib2.urlopen(req).readlines() 898042SJohn.Sonnenschein@Sun.COM except urllib2.HTTPError, e: 908042SJohn.Sonnenschein@Sun.COM if e.code != 404: 918042SJohn.Sonnenschein@Sun.COM print "ERROR: HTTP error at " + \ 928042SJohn.Sonnenschein@Sun.COM req.get_full_url() + \ 938042SJohn.Sonnenschein@Sun.COM " got error: " + str(e.code) 948042SJohn.Sonnenschein@Sun.COM raise e 958042SJohn.Sonnenschein@Sun.COM else: 968042SJohn.Sonnenschein@Sun.COM raise NonExistentBug 978042SJohn.Sonnenschein@Sun.COM except urllib2.URLError, e: 988042SJohn.Sonnenschein@Sun.COM print "ERROR: could not connect to " + \ 998042SJohn.Sonnenschein@Sun.COM req.get_full_url() + \ 1008042SJohn.Sonnenschein@Sun.COM ' got error: "' + e.reason[1] + '"' 1018042SJohn.Sonnenschein@Sun.COM raise e 1028042SJohn.Sonnenschein@Sun.COM htmlParser = htmllib.HTMLParser(None) 1038042SJohn.Sonnenschein@Sun.COM metaHtmlRe = re.compile(r'^<meta name="([^"]+)" content="([^"]*)">$') 1048042SJohn.Sonnenschein@Sun.COM for line in data: 1058042SJohn.Sonnenschein@Sun.COM m = metaHtmlRe.search(line) 1068042SJohn.Sonnenschein@Sun.COM if not m: 1078042SJohn.Sonnenschein@Sun.COM continue 1088042SJohn.Sonnenschein@Sun.COM val = urllib.unquote(m.group(2)) 1098042SJohn.Sonnenschein@Sun.COM htmlParser.save_bgn() 1108042SJohn.Sonnenschein@Sun.COM htmlParser.feed(val) 1118042SJohn.Sonnenschein@Sun.COM results[m.group(1)] = htmlParser.save_end() 1128042SJohn.Sonnenschein@Sun.COM htmlParser.close() 1138042SJohn.Sonnenschein@Sun.COM 1148042SJohn.Sonnenschein@Sun.COM if "synopsis" not in results: 1158042SJohn.Sonnenschein@Sun.COM raise NonExistentBug(cr) 1168042SJohn.Sonnenschein@Sun.COM 1178042SJohn.Sonnenschein@Sun.COM results["cr_number"] = cr 1188042SJohn.Sonnenschein@Sun.COM results["sub_category"] = results.pop("subcategory") 1198042SJohn.Sonnenschein@Sun.COM results["status"] = results.pop("state") 1208042SJohn.Sonnenschein@Sun.COM results["date_submitted"] = results.pop("submit_date") 1218042SJohn.Sonnenschein@Sun.COM 1228042SJohn.Sonnenschein@Sun.COM return results 1238042SJohn.Sonnenschein@Sun.COM 1248042SJohn.Sonnenschein@Sun.COM 1258042SJohn.Sonnenschein@Sun.COM def __monaco(self, crs): 1268042SJohn.Sonnenschein@Sun.COM """Return all info for requested change reports. 1278042SJohn.Sonnenschein@Sun.COM 1288042SJohn.Sonnenschein@Sun.COM Argument: 1298042SJohn.Sonnenschein@Sun.COM crs: list of change request ids 1308042SJohn.Sonnenschein@Sun.COM 1318042SJohn.Sonnenschein@Sun.COM Returns: 1328042SJohn.Sonnenschein@Sun.COM Dictionary, mapping CR=>dictionary, where the nested dictionary 1338042SJohn.Sonnenschein@Sun.COM is a mapping of field=>value 1348042SJohn.Sonnenschein@Sun.COM """ 13511308SOndrej.Kubecka@Sun.COM 1368042SJohn.Sonnenschein@Sun.COM # 13711308SOndrej.Kubecka@Sun.COM # See if 'maxcrs' for maximal batch query size is defined 13811308SOndrej.Kubecka@Sun.COM # if not, default to 200. 13911308SOndrej.Kubecka@Sun.COM # This clears the 2499 chars query limit 1408042SJohn.Sonnenschein@Sun.COM # 14111308SOndrej.Kubecka@Sun.COM try: 14211308SOndrej.Kubecka@Sun.COM maxcrs 14311308SOndrej.Kubecka@Sun.COM except NameError: 14411308SOndrej.Kubecka@Sun.COM maxcrs = 200 14511308SOndrej.Kubecka@Sun.COM 14611308SOndrej.Kubecka@Sun.COM i = 0 1478042SJohn.Sonnenschein@Sun.COM results = {} 14811308SOndrej.Kubecka@Sun.COM data = [] 14911308SOndrej.Kubecka@Sun.COM 15011308SOndrej.Kubecka@Sun.COM while i < len(crs): 15111308SOndrej.Kubecka@Sun.COM if len(crs) < ( i + maxcrs ): 15211308SOndrej.Kubecka@Sun.COM j = len(crs) 15311308SOndrej.Kubecka@Sun.COM else: 15411308SOndrej.Kubecka@Sun.COM j = i + maxcrs 15511308SOndrej.Kubecka@Sun.COM 15611308SOndrej.Kubecka@Sun.COM crstmp=crs[i:j] 1578042SJohn.Sonnenschein@Sun.COM 15811308SOndrej.Kubecka@Sun.COM # 15911308SOndrej.Kubecka@Sun.COM # We request synopsis last, and split on only 16011308SOndrej.Kubecka@Sun.COM # the number of separators that we expect to 16111308SOndrej.Kubecka@Sun.COM # see such that a | in the synopsis doesn't 16211308SOndrej.Kubecka@Sun.COM # throw us out of whack. 16311308SOndrej.Kubecka@Sun.COM # 16411308SOndrej.Kubecka@Sun.COM monacoFields = [ "cr_number", "category", "sub_category", 16511308SOndrej.Kubecka@Sun.COM "area", "release", "build", "responsible_manager", 16611308SOndrej.Kubecka@Sun.COM "responsible_engineer", "priority", "status", "sub_status", 16711308SOndrej.Kubecka@Sun.COM "submitted_by", "date_submitted", "synopsis" ] 16811308SOndrej.Kubecka@Sun.COM cmd = [] 16911308SOndrej.Kubecka@Sun.COM cmd.append("set What = cr." + ', cr.'.join(monacoFields)) 17011308SOndrej.Kubecka@Sun.COM cmd.append("") 17111308SOndrej.Kubecka@Sun.COM cmd.append("set Which = cr.cr_number in (" + ','.join(crstmp) +")") 17211308SOndrej.Kubecka@Sun.COM cmd.append("") 17311308SOndrej.Kubecka@Sun.COM cmd.append("set FinalClauses = order by cr.cr_number") 17411308SOndrej.Kubecka@Sun.COM cmd.append("") 17511308SOndrej.Kubecka@Sun.COM cmd.append("doMeta genQuery cr") 17611308SOndrej.Kubecka@Sun.COM url = "http://hestia.sfbay.sun.com/cgi-bin/expert?format=" 17711308SOndrej.Kubecka@Sun.COM url += "Pipe-delimited+text;Go=2;no_header=on;cmds=" 17811308SOndrej.Kubecka@Sun.COM url += urllib.quote_plus("\n".join(cmd)) 17911308SOndrej.Kubecka@Sun.COM try: 18011308SOndrej.Kubecka@Sun.COM data += urllib2.urlopen(url).readlines() 18111308SOndrej.Kubecka@Sun.COM except urllib2.HTTPError, e: 18211308SOndrej.Kubecka@Sun.COM print "ERROR: HTTP error at " + url + \ 18311308SOndrej.Kubecka@Sun.COM " got error: " + str(e.code) 18411308SOndrej.Kubecka@Sun.COM raise e 18511308SOndrej.Kubecka@Sun.COM 18611308SOndrej.Kubecka@Sun.COM except urllib2.URLError, e: 18711308SOndrej.Kubecka@Sun.COM print "ERROR: could not connect to " + url + \ 18811308SOndrej.Kubecka@Sun.COM ' got error: "' + e.reason[1] + '"' 18911308SOndrej.Kubecka@Sun.COM raise e 19011308SOndrej.Kubecka@Sun.COM 19111308SOndrej.Kubecka@Sun.COM i += maxcrs 19211308SOndrej.Kubecka@Sun.COM 1938042SJohn.Sonnenschein@Sun.COM for line in data: 1948042SJohn.Sonnenschein@Sun.COM line = line.rstrip('\n') 1958042SJohn.Sonnenschein@Sun.COM values = line.split('|', len(monacoFields) - 1) 1968042SJohn.Sonnenschein@Sun.COM v = 0 1978042SJohn.Sonnenschein@Sun.COM cr = values[0] 1988042SJohn.Sonnenschein@Sun.COM results[cr] = {} 1998042SJohn.Sonnenschein@Sun.COM for field in monacoFields: 2008042SJohn.Sonnenschein@Sun.COM results[cr][field] = values[v] 2018042SJohn.Sonnenschein@Sun.COM v += 1 20211308SOndrej.Kubecka@Sun.COM 20311308SOndrej.Kubecka@Sun.COM 2048042SJohn.Sonnenschein@Sun.COM return results 2057078Smjnelson 2067078Smjnelson def lookup(self, crs): 2077078Smjnelson """Return all info for requested change reports. 2087078Smjnelson 2097078Smjnelson Argument: 2107078Smjnelson crs: one change request id (may be integer, string, or list), 2117078Smjnelson or multiple change request ids (must be a list) 2127078Smjnelson 2137078Smjnelson Returns: 2147078Smjnelson Dictionary, mapping CR=>dictionary, where the nested dictionary 2157078Smjnelson is a mapping of field=>value 2167078Smjnelson """ 2178042SJohn.Sonnenschein@Sun.COM results = {} 2187078Smjnelson if not isinstance(crs, list): 2197078Smjnelson crs = [str(crs)] 2208042SJohn.Sonnenschein@Sun.COM for database in self.__priority: 2218042SJohn.Sonnenschein@Sun.COM if database == "bugster": 2228042SJohn.Sonnenschein@Sun.COM if self.__onSWAN: 2238042SJohn.Sonnenschein@Sun.COM results.update(self.__monaco(crs)) 2248042SJohn.Sonnenschein@Sun.COM # else we're off-swan and querying via boo, which we can 2258042SJohn.Sonnenschein@Sun.COM # only do one bug at a time 2268042SJohn.Sonnenschein@Sun.COM else: 2278042SJohn.Sonnenschein@Sun.COM for cr in crs: 2288042SJohn.Sonnenschein@Sun.COM cr = str(cr) 2298042SJohn.Sonnenschein@Sun.COM try: 2308042SJohn.Sonnenschein@Sun.COM results[cr] = self.__boobug(cr) 2318042SJohn.Sonnenschein@Sun.COM except NonExistentBug: 2328042SJohn.Sonnenschein@Sun.COM continue 2337078Smjnelson 2348042SJohn.Sonnenschein@Sun.COM # the CR has already been found by one bug database 2358042SJohn.Sonnenschein@Sun.COM # so don't bother looking it up in the others 2368042SJohn.Sonnenschein@Sun.COM for cr in crs: 2378042SJohn.Sonnenschein@Sun.COM if cr in results: 2388042SJohn.Sonnenschein@Sun.COM crs.remove(cr) 2398042SJohn.Sonnenschein@Sun.COM 2408042SJohn.Sonnenschein@Sun.COM return results 2418042SJohn.Sonnenschein@Sun.COM#################################################################### 2429920SMark.J.Nelson@Sun.COMclass ARCException(Exception): 2439920SMark.J.Nelson@Sun.COM """This covers arc.cgi script failure.""" 2449920SMark.J.Nelson@Sun.COM def __str__(self): 2459920SMark.J.Nelson@Sun.COM return "Error retrieving ARC data: %s" % (Exception.__str__(self)) 2469920SMark.J.Nelson@Sun.COM 2479920SMark.J.Nelson@Sun.COMdef ARC(arclist, arcPath=None): 2489920SMark.J.Nelson@Sun.COM if not arcPath: 249*12481SMark.J.Nelson@Oracle.COM if onSWAN(): 250*12481SMark.J.Nelson@Oracle.COM arcPath = "http://candi.sfbay.sun.com/cgi-bin/arc.cgi" 251*12481SMark.J.Nelson@Oracle.COM else: 252*12481SMark.J.Nelson@Oracle.COM arcPath = "http://arc.opensolaris.org/cgi-bin/arc.cgi" 2539920SMark.J.Nelson@Sun.COM fields = ["present", "arc", "year", "case", "status", "title"] 2549920SMark.J.Nelson@Sun.COM opts = [("case", "%s/%s" % (a, c)) for a, c in arclist] 2559920SMark.J.Nelson@Sun.COM req = urllib2.Request(arcPath, urllib.urlencode(opts)) 2568042SJohn.Sonnenschein@Sun.COM try: 2578042SJohn.Sonnenschein@Sun.COM data = urllib2.urlopen(req).readlines() 2588042SJohn.Sonnenschein@Sun.COM except urllib2.HTTPError, e: 2598174SJohn.Sonnenschein@Sun.COM print "ERROR: HTTP error at " + req.get_full_url() + \ 2608042SJohn.Sonnenschein@Sun.COM " got error: " + str(e.code) 2618042SJohn.Sonnenschein@Sun.COM raise e 2627078Smjnelson 2638042SJohn.Sonnenschein@Sun.COM except urllib2.URLError, e: 2648174SJohn.Sonnenschein@Sun.COM print "ERROR: could not connect to " + req.get_full_url() + \ 2658042SJohn.Sonnenschein@Sun.COM ' got error: "' + e.reason[1] + '"' 2668042SJohn.Sonnenschein@Sun.COM raise e 2678042SJohn.Sonnenschein@Sun.COM ret = {} 2689920SMark.J.Nelson@Sun.COM for line in csv.DictReader(data, fields): 2699920SMark.J.Nelson@Sun.COM if line["present"] == "exists": 2709920SMark.J.Nelson@Sun.COM yc = "%s/%s" % (line["year"], line["case"]) 2719920SMark.J.Nelson@Sun.COM ret[(line["arc"], yc)] = line["title"] 2729920SMark.J.Nelson@Sun.COM elif line["present"] == "fatal": 2739920SMark.J.Nelson@Sun.COM raise ARCException(line["arc"]) 2749920SMark.J.Nelson@Sun.COM 2758042SJohn.Sonnenschein@Sun.COM return ret 2767078Smjnelson 2777078Smjnelson#################################################################### 2787078Smjnelson 2797078Smjnelson# Pointers to the webrti server hostname & port to use 2807078Smjnelson# Using it directly is probably not *officially* supported, so we'll 2817078Smjnelson# have a pointer to the official `webrticli` command line interface 2827078Smjnelson# if using a direct socket connection fails for some reason, so we 2837078Smjnelson# have a fallback 2847078SmjnelsonWEBRTI_HOST = 'webrti.sfbay.sun.com' 2857078SmjnelsonWEBRTI_PORT = 9188 2867764SJohn.Sonnenschein@Sun.COMWEBRTICLI = '/net/onnv.sfbay.sun.com/export/onnv-gate/public/bin/webrticli' 2877078Smjnelson 2887078Smjnelson 2897078Smjnelsonclass RtiException(Exception): 2909920SMark.J.Nelson@Sun.COM pass 2917078Smjnelson 2927078Smjnelsonclass RtiCallFailed(RtiException): 2937078Smjnelson def __str__(self): 2949920SMark.J.Nelson@Sun.COM return "Unable to call webrti: %s" % (RtiException.__str__(self)) 2957078Smjnelson 2967078Smjnelsonclass RtiSystemProblem(RtiException): 2977078Smjnelson def __str__(self): 2989920SMark.J.Nelson@Sun.COM return "RTI status cannot be determined for CR: %s" % (RtiException.__str__(self)) 2997078Smjnelson 3007078Smjnelsonclass RtiIncorrectCR(RtiException): 3017078Smjnelson def __str__(self): 3029920SMark.J.Nelson@Sun.COM return "Incorrect CR number specified: %s" % (RtiException.__str__(self)) 3037078Smjnelson 3047078Smjnelsonclass RtiNotFound(RtiException): 3057078Smjnelson def __str__(self): 3069920SMark.J.Nelson@Sun.COM return "RTI not found for CR: %s" % (RtiException.__str__(self)) 3077078Smjnelson 3087078Smjnelsonclass RtiNeedConsolidation(RtiException): 3097078Smjnelson def __str__(self): 3109920SMark.J.Nelson@Sun.COM return "More than one consolidation has this CR: %s" % (RtiException.__str__(self)) 3117078Smjnelson 3127078Smjnelsonclass RtiBadGate(RtiException): 3137078Smjnelson def __str__(self): 3149920SMark.J.Nelson@Sun.COM return "Incorrect gate name specified: %s" % (RtiException.__str__(self)) 3159920SMark.J.Nelson@Sun.COM 3169920SMark.J.Nelson@Sun.COMclass RtiUnknownException(Exception): 3179920SMark.J.Nelson@Sun.COM def __str__(self): 3189920SMark.J.Nelson@Sun.COM return "Unknown webrti return code: %s" % (RtiException.__str__(self)) 3197078Smjnelson 3207078Smjnelsonclass RtiOffSwan(RtiException): 3217078Smjnelson def __str__(self): 3229920SMark.J.Nelson@Sun.COM return "RTI status checks need SWAN access: %s" % (RtiException.__str__(self)) 3237078Smjnelson 3247078SmjnelsonWEBRTI_ERRORS = { 3257078Smjnelson '1': RtiSystemProblem, 3267078Smjnelson '2': RtiIncorrectCR, 3277078Smjnelson '3': RtiNotFound, 3287078Smjnelson '4': RtiNeedConsolidation, 3297078Smjnelson '5': RtiBadGate, 3307078Smjnelson} 3317078Smjnelson 3327078Smjnelson# Our Rti object which we'll use to represent an Rti query 3337078Smjnelson# It's really just a wrapper around the Rti connection, and attempts 3347078Smjnelson# to establish a direct socket connection and query the webrti server 3357078Smjnelson# directly (thus avoiding a system/fork/exec call). If it fails, it 3367078Smjnelson# falls back to the webrticli command line client. 3377078Smjnelson 3387078SmjnelsonreturnCodeRe = re.compile(r'.*RETURN_CODE=(\d+)') 3397078Smjnelsonclass Rti: 3407078Smjnelson """Lookup an RTI. 3417078Smjnelson 3427078Smjnelson Usage: 3437078Smjnelson r = Rti("6640538") 3447078Smjnelson print r.rtiNumber(); 3457078Smjnelson """ 3467078Smjnelson 3477078Smjnelson def __init__(self, cr, gate=None, consolidation=None): 3487078Smjnelson """Create an Rti object for the specified change request. 3497078Smjnelson 3507078Smjnelson Argument: 3517078Smjnelson cr: change request id 3527078Smjnelson 3537078Smjnelson Keyword arguments, to limit scope of RTI search: 3547078Smjnelson gate: path to gate workspace (default=None) 3557078Smjnelson consolidation: consolidation name (default=None) 3567078Smjnelson """ 3577078Smjnelson 3587078Smjnelson bufSz = 1024 3597078Smjnelson addr = (WEBRTI_HOST, WEBRTI_PORT) 3607078Smjnelson # If the passed 'cr' was given as an int, then wrap it 3617078Smjnelson # into a string to make our life easier 3627078Smjnelson if isinstance(cr, int): 3637078Smjnelson cr = str(cr) 3647078Smjnelson self.__queryCr = cr 3657078Smjnelson self.__queryGate = gate 3667078Smjnelson self.__queryConsolidation = consolidation 3677078Smjnelson 3687764SJohn.Sonnenschein@Sun.COM self.__webRtiOutput = [] 3697764SJohn.Sonnenschein@Sun.COM self.__mainCR = [] 3707764SJohn.Sonnenschein@Sun.COM self.__rtiNumber = [] 3717764SJohn.Sonnenschein@Sun.COM self.__consolidation = [] 3727764SJohn.Sonnenschein@Sun.COM self.__project = [] 3737764SJohn.Sonnenschein@Sun.COM self.__status = [] 3747764SJohn.Sonnenschein@Sun.COM self.__rtiType = [] 3757078Smjnelson try: 3767078Smjnelson # try to use a direct connection to the 3777078Smjnelson # webrti server first 3787078Smjnelson sock = socket(AF_INET, SOCK_STREAM) 3797078Smjnelson sock.connect(addr) 3807078Smjnelson command = "WEBRTICLI/1.0\nRTIstatus\n%s\n" % cr 3817078Smjnelson if consolidation: 3827078Smjnelson command += "-c\n%s\n" % consolidation 3837078Smjnelson if gate: 3847078Smjnelson command += "-g\n%s\n" % gate 3857078Smjnelson command += "\n" 3867078Smjnelson sock.send(command) 3877078Smjnelson dataList = [] 3887078Smjnelson # keep receiving data from the socket until the 3897078Smjnelson # server closes the connection 3907078Smjnelson stillReceiving = True 3917078Smjnelson while stillReceiving: 3927078Smjnelson dataPiece = sock.recv(bufSz) 3937078Smjnelson if dataPiece: 3947078Smjnelson dataList.append(dataPiece) 3957078Smjnelson else: 3967078Smjnelson stillReceiving = False 3977078Smjnelson # create the lines, skipping the first 3987078Smjnelson # ("WEBRTCLI/1.0\n") 3997078Smjnelson data = '\n'.join(''.join(dataList).split('\n')[1:]) 4007078Smjnelson except: 4017078Smjnelson if not onSWAN(): 4027078Smjnelson raise RtiOffSwan(cr) 4037078Smjnelson 4047078Smjnelson if not os.path.exists(WEBRTICLI): 4057078Smjnelson raise RtiCallFailed('not found') 4067078Smjnelson 4077078Smjnelson # fallback to the "supported" webrticli interface 4087078Smjnelson command = WEBRTICLI 4097078Smjnelson if consolidation: 4107078Smjnelson command += " -c " + consolidation 4117078Smjnelson if gate: 4127078Smjnelson command += " -g " + gate 4137078Smjnelson command += " RTIstatus " + cr 4147078Smjnelson 4157078Smjnelson try: 4167078Smjnelson cliPipe = os.popen(command) 4177078Smjnelson except: 4187078Smjnelson # we couldn't call the webrticli for some 4197078Smjnelson # reason, so return a failure 4207078Smjnelson raise RtiCallFailed('unknown') 4217078Smjnelson 4227078Smjnelson data = cliPipe.readline() 4237078Smjnelson 4247078Smjnelson # parse the data to see if we got a return code 4257078Smjnelson # if we did, then that's bad. if we didn't, 4269920SMark.J.Nelson@Sun.COM # then our call was successful 4277078Smjnelson m = returnCodeRe.search(data) 4287078Smjnelson if m: 4299920SMark.J.Nelson@Sun.COM rc = m.group(1) 4307078Smjnelson # we got a return code, set it in our 4317078Smjnelson # object, set the webRtiOutput for debugging 4327078Smjnelson # or logging, and return a failure 4339920SMark.J.Nelson@Sun.COM if rc in WEBRTI_ERRORS: 4349920SMark.J.Nelson@Sun.COM exc = WEBRTI_ERRORS[rc] 4359920SMark.J.Nelson@Sun.COM if exc == RtiBadGate: 4369920SMark.J.Nelson@Sun.COM edata = gate 4379920SMark.J.Nelson@Sun.COM else: 4389920SMark.J.Nelson@Sun.COM edata = cr 4397078Smjnelson else: 4409920SMark.J.Nelson@Sun.COM exc = RtiUnknownException 4419920SMark.J.Nelson@Sun.COM edata = rc 4429920SMark.J.Nelson@Sun.COM raise exc(edata) 4437078Smjnelson 4447764SJohn.Sonnenschein@Sun.COM data = data.splitlines() 4457078Smjnelson # At this point, we should have valid data 4467764SJohn.Sonnenschein@Sun.COM for line in data: 4477764SJohn.Sonnenschein@Sun.COM line = line.rstrip('\r\n') 4487764SJohn.Sonnenschein@Sun.COM self.__webRtiOutput.append(line) 4497764SJohn.Sonnenschein@Sun.COM fields = line.split(':') 4507764SJohn.Sonnenschein@Sun.COM self.__mainCR.append(fields[0]) 4517764SJohn.Sonnenschein@Sun.COM self.__rtiNumber.append(fields[1]) 4527764SJohn.Sonnenschein@Sun.COM self.__consolidation.append(fields[2]) 4537764SJohn.Sonnenschein@Sun.COM self.__project.append(fields[3]) 4547764SJohn.Sonnenschein@Sun.COM self.__status.append(fields[4]) 4557764SJohn.Sonnenschein@Sun.COM self.__rtiType.append(fields[5]) 4567078Smjnelson 4577078Smjnelson # accessors in case callers need the raw data 4587078Smjnelson def mainCR(self): 4597078Smjnelson return self.__mainCR 4607078Smjnelson def rtiNumber(self): 4617078Smjnelson return self.__rtiNumber 4627078Smjnelson def consolidation(self): 4637078Smjnelson return self.__consolidation 4647078Smjnelson def project(self): 4657078Smjnelson return self.__project 4667078Smjnelson def status(self): 4677078Smjnelson return self.__status 4687078Smjnelson def rtiType(self): 4697078Smjnelson return self.__rtiType 4707078Smjnelson def queryCr(self): 4717078Smjnelson return self.__queryCr 4727078Smjnelson def queryGate(self): 4737078Smjnelson return self.__queryGate 4747078Smjnelson def queryConsolidation(self): 4757078Smjnelson return self.__queryConsolidation 4767078Smjnelson 4777078Smjnelson # in practice, most callers only care about the following 4787078Smjnelson def accepted(self): 4797764SJohn.Sonnenschein@Sun.COM for status in self.__status: 4807764SJohn.Sonnenschein@Sun.COM if status != "S_ACCEPTED": 4817764SJohn.Sonnenschein@Sun.COM return False 4827764SJohn.Sonnenschein@Sun.COM return True 4837078Smjnelson 4847078Smjnelson # for logging/debugging in case the caller wants the raw webrti output 4857078Smjnelson def webRtiOutput(self): 4867078Smjnelson return self.__webRtiOutput 4877078Smjnelson 488