[Spacewalk-list] rhn-clone-errata.py ProtocolError: 502 -Proxy Error
Speagle, Andy
andy.speagle at wichita.edu
Wed Nov 10 14:44:09 UTC 2010
> I'm using Spacewalk 1.1 with version 0.6 of the script pasted below.
Ok, I noted a couple of small changes, but I've only tested this up to v1.0 of Spacewalk. I need to upgrade my dev box and correct any bugs. I've updated the version to 0.7 to distinguish this script from other versions. Let me know you mileage.
#!/bin/env python
# Script that uses RHN API to clone RHN Errata to Satellite
# or Spacewalk server.
# Copyright (C) 2008 Red Hat
#
# Author: Andy Speagle (andy.speagle at wichita.edu)
#
# This script was written based on the "rhn-clone-errata.py"
# script written by: Lars Jonsson (ljonsson at redhat.com)
#
# (THANKS!)
#
# 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
#
# Version Information:
#
# 0.1 - 2009-09-01 - Andy Speagle
#
# Initial release. Lots of problems. Oof.
#
# 0.2 - 2009-09-11 - Andy Speagle
#
# Updated methodology for handling errata. Breaking up individual
# errata appended with a channel identifier to better automate publishing
# of errata.
#
# Some code reworking. I still suck at python. Removed deprecated "sets"
# module.
#
# 0.3 - 2009-09-17 - Andy Speagle
#
# Fixed a rather glaring bug in the logic regarding relevant channel
# for package selection. Ugh.
#
# 0.4 - 2009-10-01 - Andy Speagle
#
# Modified how the publish happens. Now it creates the errata and THEN
# calls the separate errata.publish() function. I was having some
# intermittent time-outs doing the two together in the errata.create()
# function.
#
# 0.5 - 2010-03-17 - Andy Speagle
#
# Moved servers, users and passwords to a config file of your choice.
# Many config options changed as a result. Options on the command line
# override config file options.
#
# Merged proxy support code from Colin Coe <colin.coe at gmail.com> (THANKS!)
#
# Modified some of the formatting for logfile output.
#
# I continue to suck at Python.
#
# 0.6 - 2010-03-18 - Andy Speagle
#
# Corrected a grievous bug in the new Proxy code.
#
# Moved Channel and ChannelSuffix maps to the config file.
#
# 0.7 - 2010-11-10 - Andy Speagle
#
# Minor bugfixes a/o cosmetic changes.
#
import xmlrpclib, httplib
from optparse import OptionParser
from time import time, localtime, strftime
from datetime import datetime, timedelta
import sys
import os
import re
import ConfigParser
class ProxiedTransport(xmlrpclib.Transport):
def set_proxy(self, proxy):
self.proxy = options.proxy
def make_connection(self, host):
self.realhost = host
h = httplib.HTTP(self.proxy)
return h
def send_request(self, connection, handler, request_body):
connection.putrequest("POST", "http://%s%s" % (self.realhost, handler))
def send_host(self, connection, host):
connection.putheader("Host", self.realhost)
class RHNServer:
def __init__(self,servername,user,passwd):
self.rhnServerName = servername
self.login = user
self.password = passwd
self.rhnUrl = 'https://'+self.rhnServerName+'/rpc/api'
if options.proxy is None:
self.server = xmlrpclib.Server(self.rhnUrl)
else:
proxy = ProxiedTransport()
proxy.set_proxy(options.proxy);
self.server = xmlrpclib.Server(self.rhnUrl, transport=proxy)
self.rhnSession = self.rhnLogin(self.login,self.password,0)
def rhnLogin(self, login, password, retry):
try:
rhnSession=self.server.auth.login(login,password)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(login,password,retry)
else:
print "Failed to login",f
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.rhnLogin(login,password, (retry + 1))
return rhnSession
def getErrataChannels(self,advisory,retry):
channels = []
try:
details = self.server.errata.applicableToChannels(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.applicableToChannels(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataChannels(advisory, (retry + 1))
return channels
def getErrataDetails(self,advisory,retry):
details = []
try:
details = self.server.errata.getDetails(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.getDetails(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataDetails(advisory, (retry + 1))
return details
def getErrataKeywords(self,advisory,retry):
keywords = []
try:
keywords = self.server.errata.listKeywords(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.listKeywords(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
print "Error Getting Keywords : "+advisory
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataKeywords(advisory, (retry + 1))
return keywords
def getErrataBugs(self,advisory,retry):
bugs = []
try:
bugs = self.server.errata.bugzillaFixes(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.bugzillaFixes(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
print "Error Getting Bugs : "+advisory
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataBugs(advisory, (retry + 1))
return bugs
def getErrataCVEs(self,advisory,retry):
cves=[]
try:
cves = self.server.errata.listCves(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.listCves(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
print "Error Getting CVEs : %s" % advisory
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataCVEs(advisory, (retry + 1))
return cves
def getErrataPackages(self,advisory,retry):
packages=[]
try:
packages = self.server.errata.listPackages(self.rhnSession,advisory)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.listPackages(self.rhnSession,advisory)
elif f.faultCode == -208:
if options.verbose:
print "Errata %s Doesn't Exist on %s ..." % (advisory,self.rhnServerName)
return []
else:
print "Error Getting Packages : %s" % advisory
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.getErrataPackages(advisory, (retry + 1))
return packages
def listChannelErrata(self,dest_chan,dateStart,dateEnd,retry):
out = []
try:
out = self.server.channel.software.listErrata(self.rhnSession,dest_chan,dateStart,dateEnd)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.channel.software.listErrata(self.rhnSession,dest_chan,dateStart,dateEnd)
else:
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.listChannelErrata(dest_chan,dateStart,dateEnd,(retry + 1))
return out
def findPackageChannels(self,pkgid,retry):
channels=[]
try:
channels = self.server.packages.listProvidingChannels(self.rhnSession,pkgid)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.packages.listProvidingChannels(self.rhnSession,pkgid)
else:
print "Error Finding Channels for Package : %s" % pkgid
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.server.packages.findPackageChannels(pkgid, (retrun + 1))
return channels
def cloneErrata(self,dest_chan,errata,retry):
out=[]
try:
print "Clone errata in progress, please be patient.."
out = self.server.errata.clone(self.rhnSession,dest_chan,errata)
except xmlrpclib.Fault, f:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.self.server.errata.clone(self.rhnSession,dest_chan,errata)
else:
raise
except xmlrpclib.ProtocolError, err:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.cloneErrata(dest_chan,errata, (retry + 1))
return out
class SPWServer(RHNServer):
def searchNVREA(self,name,version,release,epoch,archlabel,retry):
package=[]
try:
package = self.server.packages.findByNvrea(self.rhnSession,name,version,release,epoch,archlabel)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.packages.findByNvrea(self.rhnSession,name,version,release,archlabel)
else:
print "Error Finding Package via NVREA : %s" % name
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.searchNVREA(name,version,release,epoch,archlabel, (retry + 1))
return package
def listChannelErrata(self,dest_chan,retry):
out = []
try:
out = self.server.channel.software.listErrata(self.rhnSession,dest_chan)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d\tFault String: %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.channel.software.listErrata(self.rhnSession,dest_chan)
else:
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.listChannelErrata(dest_chan,(retry + 1))
return out
def errataPublish(self,name,channels,retry):
errata=[]
try:
errata = self.server.errata.publish(self.rhnSession,name,channels)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d - %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.publish(self.rhnSession,name,channels)
elif f.faultCode == 2601:
print "Errata Already Exists..."
return []
else:
print "Error Creating Errata!"
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.errataPublish(name,channels, (retry + 1))
return errata
def errataCreate(self,info,bugs,keywords,packages,publish,channels,retry):
new_errata=[]
try:
new_errata = self.server.errata.create(self.rhnSession,info,bugs,keywords,packages,publish,channels)
except xmlrpclib.Fault, f:
if options.verbose:
print "Fault Code: %d - %s" % (f.faultCode,f.faultString)
if f.faultCode == -20 or f.faultCode == -1:
self.rhnLogin(self.login,self.password,0)
return self.server.errata.create(self.rhnSession,info,bugs,keywords,packages,publish,channels)
elif f.faultCode == 2601:
print "Errata Already Exists..."
return []
else:
print "Error Creating Errata!"
raise
except xmlrpclib.ProtocolError, err:
if options.verbose:
print "ProtocolError: %d - %s" % (err.errcode,err.errmsg)
if retry > 3:
raise
else:
return self.errataCreate(info,bugs,keywords,packages,publish,channels, (retry + 1))
return new_errata
def parse_args():
parser = OptionParser()
parser.add_option("-s", "--spw-server", type="string", dest="spw_server",
help="Spacewalk Server (spacewalk.mydomain.org)")
parser.add_option("-S", "--rhn-server", type="string", dest="rhn_server",
help="RHN Server (rhn.redhat.com)")
parser.add_option("-u", "--spw-user", type="string", dest="spw_user",
help="Spacewalk User")
parser.add_option("-p", "--spw-pass", type="string", dest="spw_pass",
help="Spacewalk Password")
parser.add_option("-U", "--rhn-user", type="string", dest="rhn_user",
help="RHN User")
parser.add_option("-P", "--rhn-pass", type="string", dest="rhn_pass",
help="RHN Password")
parser.add_option("-f", "--config-file", type="string", dest="cfg_file",
help="Config file for servers, users and passwords.")
parser.add_option("-c", "--src-channel", type="string", dest="src_channel",
help="Source Channel Label: ie.\"rhel-x86_64-server-5\"")
parser.add_option("-b", "--begin-date", type="string", dest="bdate",
help="Beginning Date: ie. \"19000101\" (defaults to \"19000101\")")
parser.add_option("-e", "--end-date", type="string", dest="edate",
help="Ending Date: ie. \"19001231\" (defaults to TODAY)")
parser.add_option("-i", "--publish", action="store_true", dest="publish", default=False,
help="Publish Errata (into destination channels)")
parser.add_option("-x", "--proxy", type="string", dest="proxy",
help="Proxy server and port to use (e.g. proxy.company.com:3128)")
parser.add_option("-F", "--format-header", action="store_true", dest="format", default=False,
help="Format header for logfiles")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False)
parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False)
(options,args) = parser.parse_args()
return options
def main():
global chanMap
global chanSuffixMap
global RHNServer
global RHNUser
global RHNPass
global options
options = parse_args()
# Config File Format: It needs to be ConfigParser compliant:
#
# [Section]
# option=value
if (options.cfg_file):
config = ConfigParser.ConfigParser()
config.read (options.cfg_file)
if options.spw_server is None:
options.spw_server = config.get ('Spacewalk', 'spw_server')
if options.spw_user is None:
options.spw_user = config.get ('Spacewalk', 'spw_user')
if options.spw_pass is None:
options.spw_pass = config.get ('Spacewalk', 'spw_pass')
if options.rhn_server is None:
options.rhn_server = config.get ('RHN', 'rhn_server')
if options.rhn_user is None:
options.rhn_user = config.get ('RHN', 'rhn_user')
if options.rhn_pass is None:
options.rhn_pass = config.get ('RHN', 'rhn_pass')
# Here we setup our mappings from RHN to Spacewalk software channels.
# These are read from the config file in this format:
#
# [ChanMap]
# RHNChannel = SPWChannel
#
# Example:
# rhn-tools-rhel-x86_64-server-5 = rhel-x86_64-server-rhntools-5
chanMap = {}
for chan in config.options('ChanMap'):
chanMap[chan] = config.get('ChanMap', chan)
# Here we also setup mappings from RHN channels to errata suffixes.
# Since we can't easily publish automagically, while ensuring that
# the right packages go into the right channels, we're going to
# split multi-channel affecting errata into individual errata
# that are suffixed with something meaningful that identifies
# each sub-errata per channel... blah blah... Of course, modify this
# as you will. I'm not sure if this will be required in the future.
#
# [ChanSuffixMap]
# RHNChannel = ErrataSuffix
#
# Example:
# rhn-tools-rhel-x86_64-server-5 = R5-64-T
chanSuffixMap = {}
for chan in config.options('ChanSuffixMap'):
chanSuffixMap[chan] = config.get('ChanSuffixMap', chan)
if (options.spw_server and options.spw_user and options.spw_pass and
options.rhn_server and options.rhn_user and options.rhn_pass) is None:
print "try: "+sys.argv[0]+" --help"
sys.exit(2)
if chanMap[options.src_channel] is None:
print "Invalid Channel!"
sys.exit(2)
myRHN = RHNServer(options.rhn_server, options.rhn_user, options.rhn_pass)
mySPW = SPWServer(options.spw_server, options.spw_user, options.spw_pass)
dateStart = options.bdate or '19000101'
dateToday = strftime("%Y%m%d", localtime())
dateEnd = options.edate or dateToday
if options.format:
print >>sys.stdout, "%s:CLONE:%s" % (dateToday, options.src_channel)
print >>sys.stderr, "%s:CLONE:%s" % (dateToday, options.src_channel)
for rhnErrata in myRHN.listChannelErrata(options.src_channel,dateStart,dateEnd,0):
if not options.quiet and not options.format:
print rhnErrata['errata_advisory']
# Now, let's check if we already have this errata locally...
spwErrataName = rhnErrata['errata_advisory']+':'+chanSuffixMap[options.src_channel]
spwErrCheck = mySPW.getErrataDetails (spwErrataName,0)
if not spwErrCheck:
# Ok, so the errata doesn't already exists... let's get busy creating it.
spwErrSolution = "Before applying this update, make sure that all "+\
"previously-released errata relevant to your system have been applied."
spwErrPackages = []
for pkg in myRHN.getErrataPackages(rhnErrata['errata_advisory'],0):
pkgFind = mySPW.searchNVREA(pkg['package_name'],\
pkg['package_version'],\
pkg['package_release'],\
'',\
pkg['package_arch_label'],\
0)
for pkgChan in pkg['providing_channels']:
if pkgChan != options.src_channel:
continue
else:
if not pkgFind:
if options.format:
print >>sys.stderr, "%s:%s:Hmmm... "+\
"Package Missing: %s" % (dateToday, rhnErrata['errata_advisory'], pkg['package_name'])
else:
print "Hmmm... Package Missing: %s" % pkg['package_name']
else:
spwErrPackages.append(pkgFind[0]['id'])
break
spwErrDetails = myRHN.getErrataDetails(rhnErrata['errata_advisory'],0)
spwErrKeywords = myRHN.getErrataKeywords(rhnErrata['errata_advisory'],0)
spwErrBugs = []
tmpBugs = myRHN.getErrataBugs(rhnErrata['errata_advisory'],0)
for bug in tmpBugs:
spwErrBugs.append({'id': int(bug), 'summary': tmpBugs[bug]})
if not options.quiet and not options.format:
print "\t%s - %s" % (spwErrDetails['errata_issue_date'],spwErrDetails['errata_synopsis'])
spwErrObject = mySPW.errataCreate ({ 'synopsis': spwErrDetails['errata_synopsis'],\
'advisory_name': spwErrataName,\
'advisory_release': 1,\
'advisory_type': spwErrDetails['errata_type'],\
'product': 'RHEL',\
'topic': spwErrDetails['errata_topic'],\
'description': spwErrDetails['errata_description'],\
'references': spwErrDetails['errata_references'],\
'notes': spwErrDetails['errata_notes'],\
'solution': spwErrSolution },\
spwErrBugs,\
spwErrKeywords,\
spwErrPackages,\
0,\
[chanMap[options.src_channel]],\
0)
if options.format:
print "%s#%s#Errata Created#" % (dateToday, spwErrataName),
else:
print "\tErrata Created: %d" % spwErrObject['id']
if options.publish:
spwPublish = mySPW.errataPublish (spwErrataName, [chanMap[options.src_channel]], 0)
if options.format:
print "Errata Published"
else:
print "\tErrata Published!"
else:
if options.format:
print "Errata Not Published"
else:
print "\tErrata Not Published!"
else:
if options.format:
print "%s#%s#Errata Already Exists" % (dateToday, spwErrataName)
elif not options.quiet:
print "\tErrata Already Exists. %s" % spwErrataName
continue
if __name__ == "__main__":
main()
Thanks,
Andy
More information about the Spacewalk-list
mailing list