def poll_packages(self, release, server_arch, timestamp=0, uuid=None): log_debug(1, release, server_arch, timestamp, uuid) # make sure we're dealing with strings here release = str(release) server_arch = rhnLib.normalize_server_arch(server_arch) timestamp = str(timestamp) uuid = str(uuid) # get a list of acceptable channels channel_list = [] channel_list = rhnChannel.applet_channels_for_uuid(uuid) # it's possible the tie between uuid and rhnServer.id wasn't yet # made, default to normal behavior if not channel_list: channel_list = rhnChannel.get_channel_for_release_arch( release, server_arch) channel_list = [channel_list] # bork if no channels returned if not channel_list: log_debug( 8, "No channels for release = '%s', arch = '%s', uuid = '%s'" % (release, server_arch, uuid)) return {'last_modified': 0, 'contents': []} last_channel_changed_ts = max( [a["last_modified"] for a in channel_list]) # make satellite content override a cache caused by hosted last_channel_changed_ts = str(LongType(last_channel_changed_ts) + 1) # gotta be careful about channel unsubscriptions... client_cache_invalidated = None # we return rhnServer.channels_changed for each row # in the satellite case, pluck it off the first... if "server_channels_changed" in channel_list[0]: sc_ts = channel_list[0]["server_channels_changed"] if sc_ts and (sc_ts >= last_channel_changed_ts): client_cache_invalidated = 1 if (last_channel_changed_ts <= timestamp) and (not client_cache_invalidated): # XXX: I hate these freaking return codes that return # different members in the dictinary depending on what # sort of data you get log_debug(3, "Client has current data") return {'use_cached_copy': 1} # we'll have to return something big - compress rhnFlags.set("compress_response", 1) # Mark the response as being already XMLRPC-encoded rhnFlags.set("XMLRPC-Encoded-Response", 1) # next, check the cache if we have something with this timestamp label_list = [str(a["id"]) for a in channel_list] label_list.sort() log_debug(4, "label_list", label_list) cache_key = "applet-poll-%s" % string.join(label_list, "-") ret = rhnCache.get(cache_key, last_channel_changed_ts) if ret: # we have a good entry with matching timestamp log_debug(3, "Cache HIT for", cache_key) return ret # damn, need to do some real work from chip's requirements: # The package list should be an array of hashes with the keys # nvre, name, version, release, epoch, errata_advisory, # errata_id, with the errata fields being empty strings if the # package isn't from an errata. ret = {'last_modified': last_channel_changed_ts, 'contents': []} # we search for packages only in the allowed channels - build # the SQL helper string and dictionary to make the foo IN ( # list ) constructs use bind variables qlist = [] qdict = {} for c in channel_list: v = c["id"] k = "channel_%s" % v qlist.append(":%s" % k) qdict[k] = v qlist = string.join(qlist, ", ") # This query is kind of big. One of these days I'm gonna start # pulling them out and transforming them into views. We can # also simulate this using several functions exposed out of # rhnChannel, but there is no difference in speed because we # need to do more than one query; besides, we cache the hell # out of it h = rhnSQL.prepare(""" select distinct pn.name, pe.version, pe.release, pe.epoch, e_sq.errata_advisory, e_sq.errata_synopsis, e_sq.errata_id from rhnPackageName pn, rhnPackageEVR pe, rhnChannelNewestPackage cnp left join ( select sq_e.id as errata_id, sq_e.synopsis as errata_synopsis, sq_e.advisory as errata_advisory, sq_ep.package_id from rhnErrata sq_e, rhnErrataPackage sq_ep, rhnChannelErrata sq_ce where sq_ce.errata_id = sq_ep.errata_id and sq_ce.errata_id = sq_e.id and sq_ce.channel_id in ( %s ) ) e_sq on cnp.package_id = e_sq.package_id where cnp.channel_id in ( %s ) and cnp.name_id = pn.id and cnp.evr_id = pe.id """ % (qlist, qlist)) h.execute(**qdict) plist = h.fetchall_dict() if not plist: # We've set XMLRPC-Encoded-Response above ret = xmlrpclib.dumps((ret, ), methodresponse=1) return ret contents = {} for p in plist: for k in list(p.keys()): if p[k] is None: p[k] = "" p["nevr"] = "%s-%s-%s:%s" % (p["name"], p["version"], p["release"], p["epoch"]) p["nvr"] = "%s-%s-%s" % (p["name"], p["version"], p["release"]) pkg_name = p["name"] if pkg_name in contents: stored_pkg = contents[pkg_name] s = [ stored_pkg["name"], stored_pkg["version"], stored_pkg["release"], stored_pkg["epoch"] ] n = [p["name"], p["version"], p["release"], p["epoch"]] log_debug(7, "comparing vres", s, n) if rhn_rpm.nvre_compare(s, n) < 0: log_debug(7, "replacing %s with %s" % (pkg_name, p)) contents[pkg_name] = p else: # already have a higher vre stored... pass else: log_debug(7, "initial store for %s" % pkg_name) contents[pkg_name] = p ret["contents"] = list(contents.values()) # save it in the cache # We've set XMLRPC-Encoded-Response above ret = xmlrpclib.dumps((ret, ), methodresponse=1) rhnCache.set(cache_key, ret, last_channel_changed_ts) return ret
def poll_packages(self, release, server_arch, timestamp = 0, uuid = None): log_debug(1, release, server_arch, timestamp, uuid) # make sure we're dealing with strings here release = str(release) server_arch = rhnLib.normalize_server_arch(server_arch) timestamp = str(timestamp) uuid = str(uuid) # get a list of acceptable channels channel_list = [] channel_list = rhnChannel.applet_channels_for_uuid(uuid) # it's possible the tie between uuid and rhnServer.id wasn't yet # made, default to normal behavior if not channel_list: channel_list = rhnChannel.get_channel_for_release_arch(release, server_arch) channel_list = [channel_list] # bork if no channels returned if not channel_list: log_debug(8, "No channels for release = '%s', arch = '%s', uuid = '%s'" % ( release, server_arch, uuid)) return { 'last_modified' : 0, 'contents' : [] } last_channel_changed_ts = max(map(lambda a: a["last_modified"], channel_list)) # make satellite content override a cache caused by hosted last_channel_changed_ts = str(long(last_channel_changed_ts) + 1) # gotta be careful about channel unsubscriptions... client_cache_invalidated = None # we return rhnServer.channels_changed for each row # in the satellite case, pluck it off the first... if channel_list[0].has_key("server_channels_changed"): sc_ts = channel_list[0]["server_channels_changed"] if sc_ts and (sc_ts >= last_channel_changed_ts): client_cache_invalidated = 1 if (last_channel_changed_ts <= timestamp) and (not client_cache_invalidated): # XXX: I hate these freaking return codes that return # different members in the dictinary depending on what # sort of data you get log_debug(3, "Client has current data") return { 'use_cached_copy' : 1 } # we'll have to return something big - compress rhnFlags.set("compress_response", 1) # Mark the response as being already XMLRPC-encoded rhnFlags.set("XMLRPC-Encoded-Response", 1) # next, check the cache if we have something with this timestamp label_list = map(lambda a: str(a["id"]), channel_list) label_list.sort() log_debug(4, "label_list", label_list) cache_key = "applet-poll-%s" % string.join(label_list, "-") ret = rhnCache.get(cache_key, last_channel_changed_ts) if ret: # we have a good entry with matching timestamp log_debug(3, "Cache HIT for", cache_key) return ret # damn, need to do some real work from chip's requirements: # The package list should be an array of hashes with the keys # nvre, name, version, release, epoch, errata_advisory, # errata_id, with the errata fields being empty strings if the # package isn't from an errata. ret = { 'last_modified' : last_channel_changed_ts, 'contents' : [] } # we search for packages only in the allowed channels - build # the SQL helper string and dictionary to make the foo IN ( # list ) constructs use bind variables qlist = [] qdict = {} for c in channel_list: v = c["id"] k = "channel_%s" % v qlist.append(":%s" % k) qdict[k] = v qlist = string.join(qlist, ", ") # This query is kind of big. One of these days I'm gonna start # pulling them out and transforming them into views. We can # also simulate this using several functions exposed out of # rhnChannel, but there is no difference in speed because we # need to do more than one query; besides, we cache the hell # out of it h = rhnSQL.prepare(""" select distinct pn.name, pe.version, pe.release, pe.epoch, e_sq.errata_advisory, e_sq.errata_synopsis, e_sq.errata_id from rhnPackageName pn, rhnPackageEVR pe, rhnChannelNewestPackage cnp left join ( select sq_e.id as errata_id, sq_e.synopsis as errata_synopsis, sq_e.advisory as errata_advisory, sq_ep.package_id from rhnErrata sq_e, rhnErrataPackage sq_ep, rhnChannelErrata sq_ce where sq_ce.errata_id = sq_ep.errata_id and sq_ce.errata_id = sq_e.id and sq_ce.channel_id in ( %s ) ) e_sq on cnp.package_id = e_sq.package_id where cnp.channel_id in ( %s ) and cnp.name_id = pn.id and cnp.evr_id = pe.id """ % (qlist, qlist)) h.execute(**qdict) plist = h.fetchall_dict() if not plist: # We've set XMLRPC-Encoded-Response above ret = xmlrpclib.dumps((ret, ), methodresponse=1) return ret contents = {} for p in plist: for k in p.keys(): if p[k] is None: p[k] = "" p["nevr"] = "%s-%s-%s:%s" % ( p["name"], p["version"], p["release"], p["epoch"]) p["nvr"] = "%s-%s-%s" % (p["name"], p["version"], p["release"]) pkg_name = p["name"] if contents.has_key(pkg_name): stored_pkg = contents[pkg_name] s = [ stored_pkg["name"], stored_pkg["version"], stored_pkg["release"], stored_pkg["epoch"] ] n = [ p["name"], p["version"], p["release"], p["epoch"] ] log_debug(7, "comparing vres", s, n) if rhn_rpm.nvre_compare(s, n) < 0: log_debug(7, "replacing %s with %s" % (pkg_name, p)) contents[pkg_name] = p else: # already have a higher vre stored... pass else: log_debug(7, "initial store for %s" % pkg_name) contents[pkg_name] = p ret["contents"] = contents.values() # save it in the cache # We've set XMLRPC-Encoded-Response above ret = xmlrpclib.dumps((ret, ), methodresponse=1) rhnCache.set(cache_key, ret, last_channel_changed_ts) return ret