Package backend :: Package server :: Package handlers :: Package xmlrpc :: Module errata
[hide private]
[frames] | no frames]

Source Code for Module backend.server.handlers.xmlrpc.errata

  1  # 
  2  # Copyright (c) 2008--2016 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15  # Implements the errata.* functions for XMLRPC 
 16  # 
 17   
 18  # common modules imports 
 19  from spacewalk.common.rhnTranslate import _ 
 20  from spacewalk.common import rhnFlags 
 21  from spacewalk.common.rhnLib import parseRPMName 
 22  from spacewalk.common.rhnLog import log_debug, log_error 
 23  from spacewalk.common.rhnException import rhnFault 
 24   
 25  # server modules imports 
 26  from spacewalk.server.rhnHandler import rhnHandler 
 27  from spacewalk.server import rhnSQL, rhnCapability 
 28   
 29   
30 -class Errata(rhnHandler):
31 32 """ Errata class --- retrieve (via xmlrpc) package errata. """ 33
34 - def __init__(self):
35 rhnHandler.__init__(self) 36 # Exposed Errata functions: 37 self.functions = [] 38 self.functions.append('GetByPackage') # Clients v1- 39 self.functions.append('getPackageErratum') # Clients v2+ 40 self.functions.append('getErrataInfo') # clients v2+ 41 self.functions.append('getErrataNamesById')
42
43 - def GetByPackage(self, pkg, osRel):
44 """ Clients v1- Get errata for a package given "n-v-r" format 45 IN: pkg: "n-v-r" (old client call) 46 or [n,v,r] 47 osRel: OS release 48 RET: a hash by errata that applies to this package 49 (ie, newer packages are available). We also limit the scope 50 for a particular osRel. 51 """ 52 if type(pkg) == type(''): # Old client support. 53 pkg = parseRPMName(pkg) 54 log_debug(1, pkg, osRel) 55 # Stuff the action in the headers: 56 transport = rhnFlags.get('outputTransportOptions') 57 transport['X-RHN-Action'] = 'GetByPackage' 58 59 # now look up the errata 60 if type(pkg[0]) != type(''): 61 log_error("Invalid package name: %s %s" % (type(pkg[0]), pkg[0])) 62 raise rhnFault(30, _("Expected a package name, not: %s") % pkg[0]) 63 # bug#186996:adding synopsis field to advisory info 64 # client side changes are needed to access this data. 65 h = rhnSQL.prepare(""" 66 select distinct 67 e.id errata_id, 68 e.advisory_type errata_type, 69 e.advisory advisory, 70 e.topic topic, 71 e.description description, 72 e.synopsis synopsis 73 from 74 rhnErrata e, 75 rhnPublicChannelFamily pcf, 76 rhnChannelFamilyMembers cfm, 77 rhnErrataPackage ep, 78 rhnChannelPackage cp, 79 rhnChannelErrata ce, 80 rhnDistChannelMap dcm, 81 rhnPackage p 82 where 1=1 83 and p.name_id = LOOKUP_PACKAGE_NAME(:name) 84 -- map to a channel 85 and p.id = cp.package_id 86 and cp.channel_id = dcm.channel_id 87 and dcm.release = :dist 88 and dcm.org_id is null 89 -- map to an errata as well 90 and p.id = ep.package_id 91 and ep.errata_id = e.id 92 -- the errata and the channel have to be linked 93 and ce.channel_id = cp.channel_id 94 -- and the channel has to be public 95 and cp.channel_id = cfm.channel_id 96 and cfm.channel_family_id = pcf.channel_family_id 97 -- and get the erratum 98 and e.id = ce.errata_id 99 """) 100 h.execute(name=pkg[0], dist=str(osRel)) 101 return self._sanitize_result(h)
102
103 - def getPackageErratum(self, system_id, pkg):
104 """ Clients v2+ - Get errata for a package given [n,v,r,e,a,...] format 105 106 Sing-along: You say erratum(sing), I say errata(pl)! :) 107 IN: pkg: [n,v,r,e,s,a,ch,...] 108 RET: a hash by errata that applies to this package 109 """ 110 log_debug(5, system_id, pkg) 111 if type(pkg) != type([]) or len(pkg) < 7: 112 log_error("Got invalid package specification: %s" % str(pkg)) 113 raise rhnFault(30, _("Expected a package, not: %s") % pkg) 114 # Authenticate and decode server id. 115 self.auth_system(system_id) 116 # log the entry 117 log_debug(1, self.server_id, pkg) 118 # Stuff the action in the headers: 119 transport = rhnFlags.get('outputTransportOptions') 120 transport['X-RHN-Action'] = 'getPackageErratum' 121 122 name, ver, rel, epoch, arch, size, channel = pkg[:7] 123 if epoch in ['', 'none', 'None']: 124 epoch = None 125 126 # XXX: also, should arch/size/channel ever be used? 127 # bug#186996:adding synopsis field to errata info 128 # client side changes are needed to access this data. 129 h = rhnSQL.prepare(""" 130 select distinct 131 e.id errata_id, 132 e.advisory_type errata_type, 133 e.advisory advisory, 134 e.topic topic, 135 e.description description, 136 e.synopsis synopsis 137 from 138 rhnServerChannel sc, 139 rhnChannelPackage cp, 140 rhnChannelErrata ce, 141 rhnErrata e, 142 rhnErrataPackage ep, 143 rhnPackage p 144 where 145 p.name_id = LOOKUP_PACKAGE_NAME(:name) 146 and p.evr_id = LOOKUP_EVR(:epoch, :ver, :rel) 147 -- map to a channel 148 and p.id = cp.package_id 149 -- map to an errata as well 150 and p.id = ep.package_id 151 and ep.errata_id = e.id 152 -- the errata and the channel have to be linked 153 and e.id = ce.errata_id 154 and ce.channel_id = cp.channel_id 155 -- and the server has to be subscribed to the channel 156 and cp.channel_id = sc.channel_id 157 and sc.server_id = :server_id 158 """) # " emacs sucks 159 h.execute(name=name, ver=ver, rel=rel, epoch=epoch, 160 server_id=str(self.server_id)) 161 return self._sanitize_result(h)
162
163 - def _sanitize_result(self, h):
164 ret = [] 165 # sanitize the results for display in the clients 166 while 1: 167 row = h.fetchone_dict() 168 if row is None: 169 break 170 for k in row.keys(): 171 if row[k] is None: 172 row[k] = "N/A" 173 ret.append(row) 174 175 return ret
176 177 # I don't trust this errata_id business, but chip says "trust me"
178 - def getErrataInfo(self, system_id, errata_id):
179 log_debug(5, system_id, errata_id) 180 # Authenticate the server certificate 181 self.auth_system(system_id) 182 # log this thing 183 log_debug(1, self.server_id, errata_id) 184 185 client_caps = rhnCapability.get_client_capabilities() 186 log_debug(3, "Client Capabilities", client_caps) 187 multiarch = 0 188 cap_info = None 189 if client_caps and 'packages.update' in client_caps: 190 cap_info = client_caps['packages.update'] 191 if cap_info and cap_info['version'] > 1: 192 multiarch = 1 193 194 statement = """ 195 select distinct 196 pn.name, 197 pe.epoch, 198 pe.version, 199 pe.release, 200 pa.label arch 201 from 202 rhnPackageName pn, 203 rhnPackageEVR pe, 204 rhnPackage p, 205 rhnPackageArch pa, 206 rhnChannelPackage cp, 207 rhnServerChannel sc, 208 rhnErrataPackage ep 209 where 210 ep.errata_id = :errata_id 211 and ep.package_id = p.id 212 and p.name_id = pn.id 213 and p.evr_id = pe.id 214 and p.package_arch_id = pa.id 215 and sc.server_id = :server_id 216 and sc.channel_id = cp.channel_id 217 and cp.package_id = p.id 218 """ 219 220 h = rhnSQL.prepare(statement) 221 h.execute(errata_id=errata_id, server_id=self.server_id) 222 223 packages = h.fetchall_dict() 224 ret = [] 225 if not packages: 226 return [] 227 228 for package in packages: 229 if package['name'] is not None: 230 if package['epoch'] is None: 231 package['epoch'] = "" 232 233 pkg_arch = '' 234 if multiarch: 235 pkg_arch = package['arch'] or '' 236 ret.append([package['name'], 237 package['version'], 238 package['release'], 239 package['epoch'], 240 pkg_arch]) 241 return ret
242
243 - def getErrataNamesById(self, system_id, errata_ids):
244 """Return a list of RhnErrata tuples of (id, advisory_name) 245 246 IN: system_id - id of the system requesting this info (must be 247 subscribed to the channel that contains the erratas) 248 errata_ids - a list of RhnErrata ids 249 250 Only the erratas that belong to channels that the client system 251 is subscribed to are returned. If no erratas match this 252 criterion, then an empty list is returned. 253 254 """ 255 log_debug(5, system_id, errata_ids) 256 self.auth_system(system_id) 257 258 log_debug(1, self.server_id, errata_ids) 259 260 sql_list, bound_vars = _bind_list(errata_ids) 261 bound_vars.update({'server_id': self.server_id}) 262 263 sql = """SELECT DISTINCT e.id, e.advisory_name 264 FROM rhnErrata e, 265 rhnPackage p, 266 rhnChannelPackage cp, 267 rhnServerChannel sc, 268 rhnErrataPackage ep 269 WHERE e.id in (%s) AND 270 ep.errata_id = e.id AND 271 ep.package_id = p.id AND 272 sc.server_id = :server_id AND 273 sc.channel_id = cp.channel_id AND 274 cp.package_id = p.id""" 275 h = rhnSQL.prepare(sql % sql_list) 276 h.execute(**bound_vars) 277 278 return h.fetchall()
279 280
281 -def _bind_list(elems):
282 """Transform a list into an sql list with bound parameters 283 284 IN: elems - a list of elements 285 286 Returns a tuple of: 287 sql_list - a comma separated list of parameter numbers: 'p_0, p_1, p_2' 288 bound_vars - a dict of parameter names and values {'p_0': 42, 'p_1': 34} 289 290 """ 291 bound_names = [] 292 bound_vars = {} 293 for i, elem in enumerate(elems): 294 bound_vars['p_%s' % i] = elem 295 bound_names.append(':p_%s' % i) 296 sql_list = ', '.join(bound_names) 297 return sql_list, bound_vars
298 299 #----------------------------------------------------------------------------- 300 if __name__ == "__main__": 301 print("You can not run this module by itself") 302 import sys 303 sys.exit(-1) 304 #----------------------------------------------------------------------------- 305