Hi Everyone, Someone expressed interest in my hacked up version of the centos errata script available here:
http://www.bioss.ac.uk/staff/davidn/spacewalk-stuff/ I've attached my version, but its really not that well done. I changed it so that it will download messages for centos-announce from mail-archive.com , then augment the data from RHN. It will also properly create errata valid for multiple architectures. I think ive broken the other methods of loading data in the process as well, so if you want those i suggest you use the original script. Just edit the config file to your liking, then run it using the following: ./centos-errata.py -f scrape blah You need any second argument since im lazy and didnt update the arguments parsing parts of the script. I doubt anyone will actually find this useful, but perhaps some of the functions could be useful to someone who wanted to write a proper script :) -R ZettaServe Disclaimer: This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately if you have received this email by mistake and delete this email from your system. Computer viruses can be transmitted via email. The recipient should check this email and any attachments for the presence of viruses. ZettaServe Pty Ltd accepts no liability for any damage caused by any virus transmitted by this email.
centos-errata.cfg
Description: centos-errata.cfg
#!/usr/bin/python # # Script which can process CentOS errata announcements and convert # them to errata in spacewalk. Based on rhn-tool.py by Lars Jonsson # # Copyright (C) 2009 Biomathematics and Statistics Scotland # # Author: Lars Jonsson (ljons...@redhat.com) # David Nutter (dav...@bioss.ac.uk) # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # from optparse import OptionParser from datetime import datetime import sys import re import os import xmlrpclib import libxml2 import email import traceback import rpm import ConfigParser import getpass import urllib #Config constants. CONFIG_FILE="centos-errata.cfg" VALID_ARCH=set(["i386","x86_64","ia64","ppc", "alpha", "sparc", "s390", "s390(x)"]) #Things to match in centos-announce messages DIGEST_BEGIN="----------------------------------------------------------------------\n\n" DIGEST_SEPARATOR="------------------------------\n\n" ARCHIVE_SEPARATOR="From .*[A-Za-z]{3,3} [A-Za-z]{3,3} [ 0-9]{2,2} \d{2,2}:\d{2,2}:\d{2,2} \d{4,4}\n" ERRATA_SUBJECT="\[CentOS-announce\] (?P<errata_type>\w{4,4})-(?P<year>\d{4,4})(:|-)(?P<errata_id>\d{4,4})\s+(?P<other_info>.*)$" PACKAGE_LIST="([\.\w-]+.rpm)" URL_BASE="http://www.mail-archive.com/centos-annou...@centos.org/" #Tags for the different errata types in email SECURITY_ERRATA="CESA" BUG_ERRATA="CEBA" ENHANCE_ERRATA="CEEA" #Special names for errata types in spacewalk SECURITY='Security Advisory' ENHANCEMENT='Product Enhancement Advisory' BUGFIX='Bug Fix Advisory' # Library used to represent a system ID in spacewalk class RHNSystem: def __init__(self,sysid,name,lastCheckin): self.systemid=sysid self.name=name self.lastCheckin=lastCheckin # Module to represent package info as returned by findByNVREA API function # TODO: more substantial class required for package details # TODO: maybe add epoch to getNVRA (if present), also rename method class RHNPackage: def __init__(self,name,version,release,epoch,archLabel): self.id = None self.name = name self.version = version self.release = release self.epoch = epoch self.archLabel = archLabel self.path = None self.provider = None self.lastModified = datetime.today() def getNVRA(self): result = "%s-%s-%s.%s" % (self.name,self.version,self.release,self.archLabel) return result # Library which represents an Errata in spacewalk. # Used for creating and retrieving errata information # TODO: Channel and Bugs should probably be types in their own right class RHNErrata: def __init__(self): self.synopsis = None self.advisoryName = None self.advisoryRelease = 1 self.advisoryType = SECURITY self.product = None self.topic = None self.description = None self.references = "" self.notes = "" self.solution = None self.publish = False self.channelLabel = [] self.keywords=[] self.bugs=[] self.packages=[] self.issueDate = datetime.now() self.modifiedDate = datetime.now() self.updateDate = datetime.now() def getPackageIds(self): result=map((lambda pkg: pkg.id),self.packages) return result def getInfoDict(self): result={} result['synopsis']=self.synopsis result['advisory_name']=self.advisoryName result['advisory_release']=self.advisoryRelease result['advisory_type']=self.advisoryType result['product']=self.product result['topic']=self.topic result['description']=self.description result['references']=self.references result['notes']=self.notes result['solution']=self.solution return result def readyToCreate(self): info = self.getInfoDict() for required_attr in ['synopsis','advisory_name','advisory_release','advisory_type','product','topic','description','solution']: if info[required_attr] is None: return False return True def printOut(self): print "%-20s = %s" % ("Name:",self.advisoryName) print "%-20s = %s" % ("Release:",self.advisoryRelease) print "%-20s = %s" % ("Product:",self.product) print "%-20s = %s" % ("Synopsis:",self.synopsis) print "%-20s = %s" % ("Topic:",self.topic) print "%-20s = %s" % ("Description:",self.description) print "%-20s = %s" % ("Solution:",self.solution) print "%-20s = %s" % ("Target Channel:",self.channelLabel) for pkg in self.packages: print " Package: %s" % pkg.getNVRA() # Library used to communicate with Spacewalk class RHNSession: def __init__(self, servername, user, passwd): self.rhnServerName = servername self.login = user self.password = passwd self.rhnUrl = 'https://'+self.rhnServerName+'/rpc/api' self.server = xmlrpclib.Server(self.rhnUrl) self.rhnSessionKey=self.rhnLogin(self.login,self.password) def rhnLogin(self, login, password): try: rhnSessionKey=self.server.auth.login(login,password) except xmlrpclib.Fault, f: if f.faultCode==-20: print "Session expired" self.rhnLogin(login,password) else: print "Failed to login",f raise return rhnSessionKey def getSystemByName(self,profileName): out=[] try: out=self.server.system.getId(self.rhnSessionKey,profileName) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getSystemByName(profileName) else: raise systemObj=None if (len(out) > 0): systemObj = RHNSystem(out[0]['id'],out[0]['name'],out[0]['last_checkin']) return systemObj def getSystemByID(self,systemid): out=[] try: out = self.server.system.getName(self.rhnSessionKey,systemid) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getServerByID(systemid) else: raise systemObj=None if (len(out) > 0): systemObj = RHNSystem(out[0]['id'],out[0]['name'],out[0]['last_checkin']) return systemObj def getThisMachine(self): out=[] try: p = libxml2.parseDoc(file("/etc/sysconfig/rhn/systemid").read()) systemid = p.xpathEval('string(//member[* = "system_id"]/value/string)').split('-')[1] except IOError: print "systemid file not found." raise systemObj = self.getSystemByID(systemid) return systemObj #TODO: this should probably return an object rather than a dictionary def getSystemDetails(self,systemObj): out={} try: out=self.server.system.getDetails(self.rhnSessionKey,int(systemObj.systemid)) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getSystemDetails(systemObj) else: raise return out def listGroups(self,systemObj): out=[] try: out=self.server.system.listGroups(self.rhnSessionKey,int(systemObj.systemid)) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.listGroups(systemObj) else: raise return out def listUserSystems(self): out=[] try: out=self.server.system.listUserSystems(self.rhnSessionKey) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.listUserSystems() else: raise return out def listActivationKeys(self): out=[] try: out=self.server.activationkey.listActivationKeys(self.rhnSessionKey) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.listActivationKeys() else: raise return out def deleteSystems(self,systemObj): out=[] try: out=self.server.system.deleteSystems(self.rhnSessionKey,systemObj.systemid) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.deleteSystems(systemObj) else: raise return out def setGroupMembership(self,systemObj,groupid,join): out=[] try: out = self.server.system.setGroupMembership(self.rhnSessionKey,int(systemObj.systemid),groupid,join) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.setGroupMembership(systemObj,groupid,join) else: raise return out def addNote(self,systemObj,label,msg): out=[] try: out = self.server.system.addNote(self.rhnSessionKey,int(systemObj.systemid),label,msg) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.addNote(systemObj,label,msg) else: raise return out def setCustomValues(self,systemObj,customInfoDict): out=[] if not customInfoDict is None: try: out = self.server.system.setCustomValues(self.rhnSessionKey,int(systemObj.systemid),customInfoDict) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.setCustomValues(systemObj,customInfoDict) else: raise return out def setCustomValue(self,systemObj,label,value): customInfoArgs={label:value[0]} return self.setCustomValues(systemObj,customInfoArgs) def setSystemDetails(self,systemObj,detailsDict): out=0 if not detailsDict is None: try: out = self.server.system.setDetails(self.rhnSessionKey,int(systemObj.systemid),detailsDict) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.setSystemDetails(systemObj,detailsDict) else: raise return out def setNewProfileName(self,systemObj,name): out=[] try: systemObj.name=name out = self.server.system.setProfileName(self.rhnSessionKey,int(systemObj.systemid),name) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.setProfileName(systemObj,name) else: raise return out def setGroup(self, systemObj, groupname, join=1): for c in self.listGroups(): if c['system_group_name'] == groupname: sgid=c['sgid'] if int(c['subscribed']) == 1: join = 0 if join == 1: self.setGroupMembership(systemObj, int(sgid),join) print "System %s has joined %s " % systemObj.name, groupname else: self.setGroupMembership(systemObj, int(sgid),join) print "System %s has left %s" % systemObj.name, groupname def getCustomValues(self,systemObj): out={} try: out = self.server.system.getCustomValues(self.rhnSessionKey,int(systemObj.systemid)) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getCustomKeyLabels() else: raise return out def addCustomKey(self,keyLabel,keyDescription): out=0 try: out = self.server.system.custominfo.createKey(self.rhnSessionKey,keyLabel,keyDescription) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.addCustomKey(keyLabel,keyDescription) else: raise return out def getCustomKeyLabels(self): out=set() result=[] try: result = self.server.system.custominfo.listAllKeys(self.rhnSessionKey) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getCustomKeyLabels() else: raise for keyInfo in result: out.add(keyInfo['label']) return out def getErrataDetails(self,advisoryName): result=None try: result = self.server.errata.getDetails(self.rhnSessionKey,advisoryName) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.getErrataDetails(advisoryName) elif f.faultCode==-208: #This seems to be the fault returned when the errata does not exist result = None else: raise if not result is None: errata = RHNErrata() errata.advisoryName=advisoryName errata.issueDate = result['issue_date'] errata.modifiedDate = result['update_date'] errata.updateDate = result['last_modified_date'] errata.description=result['description'] errata.synopsis=result['synopsis'] errata.topic=result['topic'] errata.references=result['references'] errata.notes=result['notes'] errata.advisoryType=result['type'] else: errata = None return errata def findPackageByNVREA(self,pkg_info): result= None pkg_details = None try: #Fortunately this RPC method returns an empty list if the package does not exist, no need to handle an undocumented exception if pkg_info.epoch: result = self.server.packages.findByNvrea(self.rhnSessionKey,pkg_info.name,pkg_info.version,pkg_info.release,pkg_info.epoch,pkg_info.archLabel) else: result = self.server.packages.findByNvrea(self.rhnSessionKey,pkg_info.name,pkg_info.version,pkg_info.release,"",pkg_info.archLabel) if len(result) > 0: pkg_details = result[0] except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.findPackageByNVREA(pkg_info) else: raise if not pkg_details is None: server_pkg = RHNPackage(pkg_details['name'],pkg_details['version'],pkg_details['release'],pkg_details['epoch'],pkg_details['arch_label']) server_pkg.id = pkg_details['id'] server_pkg.path = pkg_details['path'] server_pkg.provider = pkg_details['provider'] server_pkg.lastModified=pkg_details['last_modified'] return server_pkg return None def createErrata(self,erratum): result= None #Note: this method has not been tested when the errata has any bugs or keywords. #Sending the value [{}] for bugs seems to cause a crash - maybe you need [{id:"12345",name:"foobug"}] or similar for it to work if not erratum.readyToCreate(): raise try: result = self.server.errata.create(self.rhnSessionKey,erratum.getInfoDict(),erratum.bugs,erratum.keywords,erratum.getPackageIds(),erratum.publish,erratum.channelLabel) except xmlrpclib.Fault, f: if f.faultCode==-20: self.rhnLogin(self.login,self.password) return self.createErrata(erratum) else: raise return result def establishSession(options,cmdName): if (options.server and options.login) is None: print "Please specify --server and --login. Try: "+cmdName+" --help" sys.exit(2) try: while options.passwd is None: options.passwd = getpass.getpass("RHN Password: ") except Exception, e: print "Terminal does not seem to be functional. You should specify a password with --password. Aborting." sys.exit(2) mySession = RHNSession(options.server,options.login,options.passwd) return mySession def process_args(): config = ConfigParser.SafeConfigParser() config.readfp(open(CONFIG_FILE)) parser = OptionParser(usage="%prog [options] file",version="%prog 0.1") parser.add_option("-s", "--server", type="string", dest="server", help="RHN Satellite server hostname") parser.add_option("-l", "--login", type="string", dest="login", help="RHN Login") parser.add_option("-p", "--password", type="string", dest="passwd", help="RHN password (cleartext)") parser.add_option("-f","--format",type="string",dest="format",default="digest", help="Select input format for tool. Default is digest. Valid options are digest, archive, mbox") parser.add_option("-t","--test",action="store_true",dest="testmode", default=False, help="Do not connect to the RHN server, just process the input file and print errata information. Will also print configuration information") parser.add_option("","--centos-version",type="string",dest="centos_version", help="The centos version (e.g. '5' for Centos 5.3) ") parser.add_option("","--centos-arch",type="string",dest="centos_arch", help="The CentOS architecture (e.g. i386, x86_64 etc)") parser.add_option("","--packagedir",type="string",dest="package_dir", help="Where RPM files from CentOS updates are stored") parser.add_option("","--update-channel",type="string",dest="update_channel", help="Imported errata will be published to this channel") parser.set_defaults(centos_version=config.get("centos errata","version"), centos_arch=config.get("centos errata","arch"), package_dir=config.get("centos errata","package_dir"), update_channel=config.get("centos errata","update_channel")) if config.has_option("spacewalk","server"): parser.set_defaults(server=config.get("spacewalk","server")) if config.has_option("spacewalk","password"): parser.set_defaults(password=config.get("spacewalk","password")) if config.has_option("spacewalk","login"): parser.set_defaults(login=config.get("spacewalk","login")) (options,args) = parser.parse_args() return (options,args,config) def process_pkg_file(pkgfile): #Swiped from http://www.sharms.org/blog/2009/05/21/python-rpm/ as rpm-python has no documentation #TODO: better error handling/reporting here rpmQuery = rpm.ts() try: fd = os.open(pkgfile, os.O_RDONLY) header = rpmQuery.hdrFromFdno(fd) os.close(fd) except: return None pkgInfo = RHNPackage(header['name'],header['version'],header['release'],header['epoch'],header['arch']) return pkgInfo #Load email and decide on whether to act on it #Return None if no useful errata information is found in the email or a RHNErrata object if info was found def process_msg(msg_text,options): subject_re = re.compile(ERRATA_SUBJECT) packagelist_re = re.compile(PACKAGE_LIST) sec_info_re = re.compile("(?P<severity>\w+) CentOS "+options.centos_version+" "+options.centos_arch+"\s+(?P<synopsis>.*)$") bug_info_re = re.compile("CentOS "+options.centos_version+" "+options.centos_arch+"\s+(?P<synopsis>.*)$" ) enhance_info_re = re.compile("CentOS "+options.centos_version+" "+options.centos_arch+"\s+(?P<synopsis>.*)$" ) try: errataMsg = email.message_from_string(msg_text) stripNewLine = re.compile('\n') subject = errataMsg.get("Subject") if subject is None: return None subject = stripNewLine.sub("",subject) subject_match = subject_re.match(subject) if not subject_match is None: errata_type = subject_match.group('errata_type') erratum = RHNErrata() erratum.product = "CentOS "+options.centos_version+" "+options.centos_arch erratum.advisoryName = errata_type+"-"+subject_match.group('year')+":"+subject_match.group('errata_id') erratum.channelLabel = options.update_channel erratum.publish = True if errata_type == SECURITY_ERRATA: info_match = sec_info_re.match(subject_match.group('other_info')) erratum.advisoryType=SECURITY elif errata_type == BUG_ERRATA: info_match = bug_info_re.match(subject_match.group('other_info')) erratum.advisoryType=BUGFIX elif errata_type == ENHANCE_ERRATA: info_match = enhance_info_re.match(subject_match.group('other_info')) erratum.advisoryType=ENHANCEMENT else: print "Unknown errata type %s, assuming type BUG" % subject_match.group('errata_type') errata_type = BUG_ERRATA erratum.advisoryType=BUGFIX info_match = bug_info_re.match(subject_match.group('other_info')) if not info_match is None: rhn_url = "https://rhn.redhat.com/errata/"+errata_type+"-"+subject_match.group('year')+"-"+subject_match.group('errata_id')+".html" rhn_url=re.sub(r"/CE","/RH",rhn_url) erratum.topic=rhn_url erratum.description="Automatically imported CentOS erratum" erratum.solution="Install these packages to correct the erratum" if info_match.groupdict().has_key('severity'): erratum.synopsis= info_match.group('severity')+": "+info_match.group('synopsis') else: erratum.synopsis= info_match.group('synopsis') #Process the packages list, ignoring SRPMs for pkgfile in packagelist_re.findall(errataMsg.get_payload()): if not pkgfile.endswith(".src.rpm"): pkg_info = process_pkg_file(options.package_dir+pkgfile) if not pkg_info is None: erratum.packages.append(pkg_info) else: print "Package %s%s does not exist or cannot be read. Skipping errata %s" % (options.package_dir,pkgfile,erratum.advisoryName) return None return erratum else: pass print "Errata '%s' is inapplicable to the targeted CentOS release " % re.sub("\s+"," ",subject) else: print "Message with subject '%s' does not appear to be an errata" % subject except Exception, e: print "Failed to process message. Reason:" print e traceback.print_exc(file=sys.stdout) return None def download_errata(config): parsed_errata = 0 max_errata = 10000 if config.has_option("centos errata", "max_errata") is True: max_errata = config.getint("centos errata", "max_errata") messages_list_f = urllib.urlopen(URL_BASE+"maillist.html") s = messages_list_f.read() messages_list_f.close() lines = s.split("\n") subjects_re = re.compile("<span class=\"subject\"><a name=\"(?P<msgid>\d+)\" href=\"(?P<relurl>[\w.]+)\">(?P<subject>[^<]+)</a></span>") erratum_subject_re = re.compile(ERRATA_SUBJECT) packagelist_re = re.compile("([\.\w-]+.rpm)") sec_info_re = re.compile("(?P<severity>\w+) CentOS\s+(?P<version>\d)\s+(?P<arch>\w+)\s+(?P<synopsis>.*)$") bug_info_re = re.compile("CentOS\s+(?P<version>\d)\s+(?P<arch>\w+)\s+(?P<synopsis>.*)$" ) enhance_info_re = re.compile("CentOS\s+(?P<version>\d)\s+(?P<arch>\w+)\s+(?P<synopsis>.*)$" ) rhn_details_re = re.compile("<h2>Details</h2>(\s+)<div class=\"page-summary\">(?P<details>[\w\W\s]+)</div>(\s+)<br />(\s+)<h2>Solution</h2>") rhn_solution_re = re.compile("<h2>Solution</h2>(\s+)<div class=\"page-summary\">(?P<solution>[\w\W\s]+)</div>(\s+)<br />(\s+)<h2>Updated packages</h2>") errata_list = {} for line in lines: subjects_match = subjects_re.match(line) if not subjects_match is None and parsed_errata < max_errata: erratum_subject_match = erratum_subject_re.match(subjects_match.group('subject')) if not erratum_subject_match is None: advisory_name = erratum_subject_match.group('errata_type')+"-"+erratum_subject_match.group('year')+":"+erratum_subject_match.group('errata_id') if errata_list.has_key(advisory_name) is False: erratum = RHNErrata() else: erratum = errata_list[advisory_name] erratum.advisoryName = advisory_name relurl = subjects_match.group('relurl') errata_type = erratum_subject_match.group('errata_type') if errata_type == SECURITY_ERRATA: info_match = sec_info_re.match(erratum_subject_match.group('other_info')) erratum.advisoryType=SECURITY elif errata_type == BUG_ERRATA: info_match = bug_info_re.match(erratum_subject_match.group('other_info')) erratum.advisoryType=BUGFIX elif errata_type == ENHANCE_ERRATA: info_match = enhance_info_re.match(erratum_subject_match.group('other_info')) erratum.advisoryType=ENHANCEMENT else: print "Unknown errata type %s, assuming type BUG" % erratum_subject_match.group('errata_type') errata_type = BUG_ERRATA erratum.advisoryType=BUGFIX info_match = bug_info_re.match(erratum_subject_match.group('other_info')) if not info_match is None: erratum_arch = info_match.group('arch') if config.has_option(erratum_arch, "channel") is True and info_match.group('version') == config.get("centos errata", "version"): erratum.channelLabel.append(config.get(erratum_arch, "channel")) erratum.product = "CentOS "+info_match.group('version') erratum.publish = True rhn_url = "https://rhn.redhat.com/errata/"+errata_type+"-"+erratum_subject_match.group('year')+"-"+erratum_subject_match.group('errata_id')+".html" rhn_url=re.sub(r"/CE","/RH",rhn_url) erratum.topic = rhn_url if info_match.groupdict().has_key('severity'): erratum.synopsis = info_match.group('severity')+": "+info_match.group('synopsis').replace('\t', ' ') else: erratum.synopsis = info_match.group('synopsis').replace('\t', ' ') print "Downloading package data for " + advisory_name message_f = urllib.urlopen(URL_BASE+subjects_match.group('relurl')) message_src = message_f.read() message_f.close() pkg_dir = config.get(erratum_arch,"package_dir") #Process the packages list, ignoring SRPMs for pkgfile in packagelist_re.findall(message_src): if not pkgfile.endswith(".src.rpm"): pkg_info = process_pkg_file(pkg_dir+pkgfile) if not pkg_info is None: erratum.packages.append(pkg_info) else: print "Package %s%s does not exist or cannot be read. Errata may %s be incomplete" % (pkg_dir,pkgfile,erratum.advisoryName) #print "Package %s%s does not exist or cannot be read. Skipping errata %s" % (pkg_dir,pkgfile,erratum.advisoryName) #return None if erratum.description is None: print "Downloading RHN data for " + advisory_name message_f = urllib.urlopen(rhn_url) message_src = message_f.read() message_f.close() for details in rhn_details_re.findall(message_src): erratum.description = details[1] erratum.description = erratum.description.replace("<br />*", "\n*") erratum.description = erratum.description.replace("<br />", "\n") erratum.description = erratum.description.replace("<p>", "") erratum.description = erratum.description.replace("</p>", "") erratum.description = erratum.description.replace(""", "'") erratum.description = erratum.description.replace("Red Hat Enterprise Linux", "CentOS") if erratum.description is None: erratum.description ="Automatically imported CentOS erratum" if erratum.solution is None: erratum.solution = "Install these packages to correct the erratum" errata_list[advisory_name] = erratum parsed_errata += 1 else: print "Errata '%s' is inapplicable to the targeted CentOS release " % subjects_match.group('subject') else: print "Errata '%s' doesnt look like an erratum " % line return errata_list def main(): (options,args,config) = process_args() inputFile = args[0] errata=[] if not options.format == "scrape": if inputFile is None: print "I need an input filename. See %s --help" % sys.argv[0] sys.exit(2) elif not os.path.exists(inputFile): print "Input file %s does not exist" % inputFile sys.exit(2) elif not os.path.isfile(inputFile): print "Input file %s is not a normal file" % inputFile sys.exit(2) elif not os.access(inputFile,os.R_OK): print "Input file %s is not readable" % inputFile sys.exit(2) if not os.path.exists(options.package_dir): print "Package directory %s does not exist" % options.package_dir sys.exit(2) elif not os.path.isdir(options.package_dir): print "Package dir %s is not a directory" % options.package_dir sys.exit(2) elif not os.access(options.package_dir,os.R_OK): print "Package dir %s is not readable" % options.package_dir sys.exit(2) if not options.centos_arch in VALID_ARCH: print "%s does not appear to be a valid architecture" % options.centos_arch sys.exit(2) if options.testmode: print "Current configuration:" for option,value in options.__dict__.items(): print "%-20s = %s" % (option,value) print "Max errata = " + config.get("centos errata", "max_errata") else: session = establishSession(options,sys.argv[0]) if not options.format == "scrape": try: inputData=open(inputFile).read() except IOError,msg: print "Failed to read %s. Reason" print msg sys.exit(2) if options.format == "digest": digestMsg=email.message_from_string(inputData) if digestMsg.is_multipart(): print "Don't know how to handle multipart messages" sys.exit(2) #TODO: catch index exception here if we don't have a digest digestPayloads = digestMsg.get_payload().split(DIGEST_BEGIN)[1] for msg in digestPayloads.split(DIGEST_SEPARATOR): new_errata = process_msg(msg,options) if not new_errata is None: errata.append(new_errata) elif options.format == "mbox": print "Not supported just now" sys.exit(2) elif options.format == "archive": #Split on lines formmated thusly: From kbsingh at centos.org Thu Jan 8 16:25:09 2009 splitter = re.compile(ARCHIVE_SEPARATOR) for msg in splitter.split(inputData): new_errata = process_msg(msg,options) if not new_errata is None: errata.append(new_errata) elif options.format == "scrape": errata_dict = download_errata(config) errata = [] for key in errata_dict.keys(): errata.append(errata_dict[key]) else: print "Unknown input format %s" % options.format sys.exit(2) #Process any errata we have if len(errata) > 0: print "Processing %d errata..." % len(errata) for erratum in errata: try: if options.testmode: print "In test mode. Not checking server for existing erratum %s" % erratum.advisoryName erratum.printOut() print "------" else: skip = False if not session.getErrataDetails(erratum.advisoryName) is None: print "Errata %s already exists on server, skipping" % erratum.advisoryName continue for pkg_info in erratum.packages: rhn_pkg_info = session.findPackageByNVREA(pkg_info) if not rhn_pkg_info is None: pkg_info.id=rhn_pkg_info.id else: print "Package %s is not available on the server. " % pkg_info.getNVRA skip = True if skip: print "Skipping erratum %s due to missing packages" % erratum.advisoryName continue else: print "Posting erratum %s to spacewalk server." % erratum.advisoryName session.createErrata(erratum) except Exception,e: print "An exception occured when communicating with the server. Skipping erratum %s. Reason:" % erratum.advisoryName print e traceback.print_exc(file=sys.stdout) if __name__ == "__main__": main()
_______________________________________________ Spacewalk-list mailing list Spacewalk-list@redhat.com https://www.redhat.com/mailman/listinfo/spacewalk-list