Example #1
0
    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'],
        }
Example #2
0
    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
Example #3
0
 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
Example #5
0
 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
Example #6
0
    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
Example #7
0
 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