def __getV2(self, action, dry_run=0): """ Fetches queued actions for the clients version 2+. """ log_debug(3, self.server_id) # Get the root dir of this install try: method = getMethod.getMethod(action['method'], 'server.action') except getMethod.GetMethodException: Traceback("queue.get V2") raise EmptyAction("Could not get a valid method for %s" % ( action['method'],)) # Call the method result = method(self.server_id, action['id'], dry_run) if result is None: # None are mapped to the empty list result = () elif not isinstance(result, TupleType): # Everything other than a tuple is wrapped in a tuple result = (result, ) xmlblob = xmlrpclib.dumps(result, methodname=action['method']) log_debug(5, "returning xmlblob for action", xmlblob) return { 'id' : action['id'], 'action' : xmlblob, 'version' : action['version'], }
def __errataUpdate(self, actionId): """ Old client errata retrieval. """ log_debug(3, self.server_id, actionId) # get the names of the packages associated with each errata and # look them up in channels subscribed to by the server and select # the latest version sql = """ select pn.name name, pl.evr.version version, pl.evr.release release from ( select p.name_id, max(pe.evr) evr from rhnPackageEVR pe, rhnChannelPackage cp, rhnPackage p, rhnServerChannel sc, ( select p_name.name_id id from rhnActionErrataUpdate aeu, rhnErrataPackage ep, rhnPackage p_name where aeu.action_id = :action_id and aeu.errata_id = ep.errata_id and ep.package_id = p_name.id ) nids where nids.id = p.name_id and p.evr_id = pe.id and p.id = cp.package_id and cp.channel_id = sc.channel_id and sc.server_id = :server_id group by p.name_id ) pl, rhnPackageName pn where pn.id = pl.name_id """ h = rhnSQL.prepare(sql) h.execute(action_id = actionId, server_id = self.server_id) packages = [] while 1: ret = h.fetchone_dict() if not ret: break # older clients have issues with real epochs, se they are # kind of irrelevant packages.append([ret["name"], ret["version"], ret["release"], '']) xml = xmlrpclib.dumps((packages,), methodname='client.update_packages') return xml
def __getV1(self, action): """ Fetches old queued actions for the client version 1. """ log_debug(3, self.server_id) actionId = action['id'] method = action["method"] if method == 'packages.update': xml = self.__packageUpdate(actionId) elif method == 'errata.update': xml = self.__errataUpdate(actionId) elif method == 'hardware.refresh_list': xml = xmlrpclib.dumps(("hardware",), methodname="client.refresh") elif method == 'packages.refresh_list': xml = xmlrpclib.dumps(("rpmlist",), methodname="client.refresh") else: # Unrecognized, skip raise InvalidAction("Action method %s unsupported by " "Update Agent Client" % method) # all good return {'id': actionId, 'version': 1, 'action': xml}
def certificate(self): """ convert to XML """ dump = self.attrs dump["checksum"] = self.__checksum dump["fields"] = self.__fields try: x = xmlrpclib.dumps((dump,)) except TypeError, e: log_error("Could not marshall certificate for %s" % dump) e.args = e.args + (dump,) # Carry on the information for the exception reporting raise
def _encode_header(self): assert(self.header is not None) stream = tempfile.TemporaryFile() data = xmlrpclib.dumps((_replace_null(self.header), )) if self.header_flags & MPM_HEADER_COMPRESSED_GZIP: f = gzip.GzipFile(None, "wb", 9, stream) f.write(data) f.close() else: stream.write(data) stream.flush() stream.seek(0, 2) size = stream.tell() stream.seek(0, 0) return stream, size
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 name, pe.version version, pe.release release, pe.epoch epoch, e_sq.errata_advisory errata_advisory, e_sq.errata_synopsis errata_synopsis, e_sq.errata_id errata_id from rhnPackageName pn, rhnPackageEVR pe, ( select sq_e.id errata_id, sq_e.synopsis errata_synopsis, sq_e.advisory 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, rhnChannelNewestPackage cnp where cnp.channel_id in ( %s ) and cnp.name_id = pn.id and cnp.evr_id = pe.id and cnp.package_id = e_sq.package_id(+) """ % (qlist, qlist)) apply(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
def __packageUpdate(self, actionId): """ Old client package retrieval. """ log_debug(3, self.server_id, actionId) # The SQL query is a union of: # - packages with a specific EVR # - the latest packages (no EVR specified) # XXX Should we want to schedule the install for a specific version, # we'll have to modify this statement = """ select distinct pkglist.name name, -- decode the evr object selected earlier pkglist.evr.version version, pkglist.evr.release release from ( -- get the max of the two possible cases select pl.name name, max(pl.evr) evr from ( -- if the EVR is specifically requested... select pn.name name, pe.evr evr from rhnActionPackage ap, rhnPackage p, rhnPackageName pn, rhnPackageEVR pe, rhnServerChannel sc, rhnChannelPackage cp where ap.action_id = :action_id and ap.evr_id is NOT NULL and ap.evr_id = p.evr_id and ap.evr_id = pe.id and ap.name_id = p.name_id and ap.name_id = pn.id and p.id = cp.package_id and cp.channel_id = sc.channel_id and sc.server_id = :server_id UNION -- when no EVR requested, we need to compute the max available -- from the channels the server is subscribed to select pn.name name, max(pevr.evr) evr from rhnActionPackage ap, rhnServerChannel sc, rhnChannelPackage cp, rhnPackage p, rhnPackageEVR pevr, rhnPackageName pn where ap.action_id = :action_id and ap.evr_id is null and ap.name_id = pn.id and ap.name_id = p.name_id and p.evr_id = pevr.id and sc.server_id = :server_id and sc.channel_id = cp.channel_id and cp.package_id = p.id group by pn.name ) pl group by pl.name ) pkglist """ h = rhnSQL.prepare(statement) h.execute(action_id = actionId, server_id = self.server_id) ret = h.fetchall_dict() or [] packages = [] for p in ret: # old clients have issues dealing with real epochs, so we # kind of fake it for now in here entry = [p['name'], p['version'], p['release'], ''] packages.append(entry) xml = xmlrpclib.dumps((packages,), methodname='client.update_packages') return xml