#!/usr/bin/python import os import sys import cgi import traceback import types sys.stderr = sys.stdout serversToUseLocal = { "geeko.linuxdev.us.dell.com": "hb.us.dell.com", } osarchmap = { 'el3-i386': 'rh30', 'el3-x86_64': 'rh30_64', 'el4-i386': 'rh40', 'el6-x86_64': 'rh60_64', 'el5-i386': 'rh50', 'el5-x86_64': 'rh50_64', 'sles9-i386': 'suse9', 'sles9-x86_64': 'suse9_64', 'sles10-i386': 'suse10', 'sles10-x86_64': 'suse10_64', 'sles11-i386': 'suse11', 'sles11-x86_64': 'suse11_64', } debuglog = [] def dprintlog(): for line in debuglog: print line def dprint(s=""): global debuglog debuglog.append(s) def getRpmPath(rpmName, repoPath): # speed things up by not importing xml stuff for the common case. (hopefully) import xml.dom.minidom import gzip primary = os.path.join(repoPath, "repodata", "primary.xml.gz") f = gzip.GzipFile(primary, "r") dprint("# looking for %s" % rpmName) dom = xml.dom.minidom.parseString(f.read()) for nodeElem in iterNodeElement( dom, "metadata", "package" ): arch = getNodeText(getNodeElement(nodeElem, "arch")) name = getNodeText(getNodeElement(nodeElem, "name")) location = getNodeAttribute(nodeElem, "href", "location") dprint("# rpm %s.%s at %s"% (name, arch, location)) if arch == "src": continue if name == rpmName: return location raise Exception() def xformOsArch2Dir(osName, baseArch, native): if native == '0' and baseArch == 'x86_64': baseArch = 'i386' return osarchmap.get("%s-%s" % (osName, baseArch), "UNKNOWN_OS") def handleVariants(osname): # RHEL variants if osname.startswith("el3"): osname = "el3" if osname.startswith("rhel3"): osname = "el3" if osname.startswith("el4"): osname = "el4" if osname.startswith("rhel4"): osname = "el4" if osname.startswith("el5"): osname = "el5" if osname.startswith("rhel5"): osname = "el5" if osname.startswith("el6"): osname = "el6" if osname.startswith("rhel6"): osname = "el6" if osname.startswith("el7"): osname = "el7" if osname.startswith("rhel7"): osname = "el7" # Fedora backwards compat with old %{dist} if osname.startswith("fc"): osname = "f" + osname[2:] # Fedora BETA stuff # Roger Lopez TODO: fix the below to do pattern matching: f$NUM.xxx -> f$NUM+1 if osname.startswith("f7."): osname = "f8" if osname.startswith("f8."): osname = "f9" if osname.startswith("f9."): osname = "f10" return osname # handles the case where cgi is called like mirrors.cgi/options.. # rather than mirrors.cgi?options... def handlePathInfo(pathInfo): altInput = {} if pathInfo: for pair in pathInfo[1:].split("&"): name, value = pair.split("=") altInput[name] = value return altInput def xformServerName(serverName): return serversToUseLocal.get(serverName, serverName) def sanitize_hex(n): if not n.startswith("0x"): n = "0x" + n try: return "0x%04x" % int(n,16) except ValueError: return "0x0000" def main(): print 'Content-type: text/plain' form = cgi.FieldStorage() scriptDir = os.path.realpath(os.path.dirname(sys.argv[0])) pathInfo = os.environ.get("PATH_INFO", "") scriptFilename = os.environ.get("SCRIPT_FILENAME", os.path.realpath(sys.argv[0])) scriptName = os.environ.get("SCRIPT_NAME", ""); serverName = os.environ.get("SERVER_NAME", "") serverPort = os.environ.get("SERVER_PORT", "80") baseWebPath = os.path.dirname(scriptName) altInput = handlePathInfo(pathInfo) def get(name, default=None): return altInput.get(name, form.getvalue(name, default)) rpmName = get('getrpm', None) osName = get('osname', 'null_OS') baseArch = get('basearch', 'null_ARCH') native = get('native', '0') debug = get('debug', False) redirPath = get('redirpath', None) venid = sanitize_hex(get('sys_ven_id', "0x0000")) devid = sanitize_hex(get('sys_dev_id', "0x0000")) osName = handleVariants(osName) serverName = xformServerName(serverName) subdir = xformOsArch2Dir(osName, baseArch, native) sysidpath = "system.ven_%s.dev_%s" % (venid, devid) if not os.path.exists(os.path.join(scriptDir, sysidpath, subdir)): sysidpath="platform_independent" if not os.path.exists(os.path.join(scriptDir, sysidpath, subdir)): subdir="emptyrepo" url = "http://%s%s/%s/%s" % (serverName, baseWebPath, sysidpath, subdir) # if we hit this, something is physically wrong with the repo, this dir # should always exist if not os.path.exists(os.path.join(scriptDir, sysidpath, subdir)): print "Status: 404 Not Found" url = "# REPOSITORY CONFIGURATION ERROR: Please notify repository admin." if rpmName: url = url + "/" + getRpmPath(rpmName, os.path.join(scriptDir, sysidpath, subdir)) if redirPath is not None: print "Status: 301 Moved Permanently"; print "Location: %s%s" % (url, redirPath) print print url dprint("# scriptDir : %s" % scriptDir) dprint("# osName : %s" % osName) dprint("# baseArch : %s" % baseArch) dprint("# native : %s" % native) dprint("# serverName : %s" % serverName) dprint("# scriptName : %s" % scriptName) dprint("# rpmName : %s" % rpmName) if debug: dprintlog() # # XML Helper functions # def getText(nodelist): rc = "" if nodelist is not None: for node in nodelist: if node.nodeType == node.TEXT_NODE or node.nodeType == node.CDATA_SECTION_NODE: rc = rc + node.data return rc def getNodeText( node, *args ): rc = "" node = getNodeElement(node, *args) if node is not None: rc = getText( node.childNodes ) return rc def getNodeElement( node, *args ): if len(args) == 0: return node if node is not None: for search in node.childNodes: if isinstance(args[0], types.StringTypes): if search.nodeName == args[0]: candidate = getNodeElement( search, *args[1:] ) if candidate is not None: return candidate else: if search.nodeName == args[0][0]: attrHash = args[0][1] found = 1 for (key, value) in attrHash.items(): if search.getAttribute( key ) != value: found = 0 if found: candidate = getNodeElement( search, *args[1:] ) if candidate is not None: return candidate return None def iterNodeElement( node, *args ): if len(args) == 0: yield node elif node is not None: for search in node.childNodes: if isinstance(args[0], types.StringTypes): if search.nodeName == args[0]: for elem in iterNodeElement( search, *args[1:] ): yield elem else: if search.nodeName == args[0][0]: attrHash = args[0][1] found = 1 for (key, value) in attrHash.items(): if search.getAttribute( key ) != value: found = 0 if found: for elem in iterNodeElement( search, *args[1:] ): yield elem def getNodeAttribute(node, attrName, *args ): attribute = None aNode = getNodeElement(node, *args) if aNode is not None: attribute = aNode.getAttribute(attrName) if attribute == '': attribute = None return attribute if __name__ == "__main__": try: main() except Exception, e: print traceback.print_exc()