ó
½-'Nc           @   s  d  d l  Z  d  d l Z d  d l Z d  d l Z d  d l Z d  d l m Z m Z d  d l m	 Z	 d  d l
 m Z m Z d  d l m Z d  d l m Z d  d l m Z m Z m Z d  d l m Z d	 Z d
 Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d „  Z d „  Z d S(   iÿÿÿÿN(   t   Deferredt   succeed(   t   sequence_to_ranges(   t   gather_resultst   spawn_process(   t   fetch_async(   t
   touch_file(   t   PackageTaskHandlerConfigurationt   PackageTaskHandlert   run_task_handler(   t   UnknownHashIDRequesti   iô  t   PackageReporterConfigurationc           B   s   e  Z d  Z d „  Z RS(   s=   Specialized configuration for the Landscape package-reporter.c         C   s8   t  t |  ƒ j ƒ  } | j d d t d d d d ƒ| S(   sl   
        Specialize L{Configuration.make_parser}, adding options
        reporter-specific options.
        s   --force-smart-updatet   defaultt   actiont
   store_truet   helps   Force running smart-update.(   t   superR   t   make_parsert
   add_optiont   False(   t   selft   parser(    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR      s
    (   t   __name__t
   __module__t   __doc__R   (    (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR      s   t   PackageReporterc           B   sÂ   e  Z d  Z e Z d Z d Z d Z d Z d Z	 d „  Z
 d „  Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   sø   Report information about the system packages.

    @cvar queue_name: Name of the task queue to pick tasks from.
    @cvar smart_update_interval: Time interval in minutes to pass to
        the C{--after} command line option of C{smart-update}.
    t   reporteri<   s   /usr/lib/landscape/smart-updates   /etc/apt/sources.lists   /etc/apt/sources.list.dc            s´   t  ƒ  } | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j ‡  f d †  ƒ | j d  ƒ | S(   Nc            s
   ˆ  j  ƒ  S(   N(   t   run_smart_update(   t   x(   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   <lambda>;   s    c            s
   ˆ  j  ƒ  S(   N(   t   fetch_hash_id_db(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   >   s    c            s
   ˆ  j  ƒ  S(   N(   t   use_hash_id_db(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   A   s    c            s
   ˆ  j  ƒ  S(   N(   t   handle_tasks(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   D   s    c            s
   ˆ  j  ƒ  S(   N(   t   remove_expired_hash_id_requests(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   G   s    c            s
   ˆ  j  ƒ  S(   N(   t   request_unknown_hashes(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   J   s    c            s
   ˆ  j  ƒ  S(   N(   t   detect_changes(   R   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   M   s    (   R    t   addCallbackt   callbackt   None(   R   t   result(    (   R   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   run6   s    	c            s,   ‡  f d †  } ˆ  j  ƒ  } | j | ƒ | S(   sî  
        Fetch the appropriate pre-canned database of hash=>id mappings
        from the server. If the database is already present, it won't
        be downloaded twice.

        The format of the database filename is <uuid>_<codename>_<arch>,
        and it will be downloaded from the HTTP directory set in
        config.package_hash_id_url, or config.url/hash-id-databases if
        the former is not set.

        Fetch failures are handled gracefully and logged as appropriate.
        c            s¼   ˆ d  k r d  St j j ˆ ƒ r& d  Sˆ j ƒ  } | sI t j d ƒ d  St | t j j ˆ ƒ ƒ ‰  ‡  ‡ f d †  } d „  } t	 ˆ  d ˆ j
 j d ƒ ƒ} | j | ƒ | j | ƒ | S(   Ns)   Can't determine the hash=>id database urlc            s;   t  ˆ d ƒ } | j |  ƒ | j ƒ  t j d ˆ  ƒ d  S(   Nt   ws$   Downloaded hash=>id database from %s(   t   opent   writet   closet   loggingt   info(   t   datat   hash_id_db_fd(   t   urlt   hash_id_db_filename(    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   fetch_oks   s    
c         S   s$   |  j  } t j d t | ƒ ƒ d  S(   Ns'   Couldn't download hash=>id database: %s(   t   valueR-   t   warningt   str(   t   failuret	   exception(    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   fetch_errory   s    		t   cainfot   ssl_public_key(   R&   t   ost   patht   existst   _get_hash_id_db_base_urlR-   R5   R6   t   basenameR   t   _configt   getR$   t
   addErrback(   R2   t   base_urlR3   R9   R'   (   R   (   R1   R2   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   fetch_it`   s     		(   t   _determine_hash_id_db_filenameR$   (   R   RE   R'   (    (   R   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   R   s    %c         C   sc   |  j  j d ƒ } | sR |  j  j d ƒ s. d  St j |  j  j j d ƒ d ƒ } n  | j d ƒ d S(   Nt   package_hash_id_urlR1   t   /s   hash-id-databases(   RA   RB   R&   t   urlparset   urljoinR1   t   rstrip(   R   RD   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR?   ‰   s    c         C   sØ   d d l  m } g  } t j j |  j ƒ r> | j |  j ƒ n  t j j |  j ƒ r” | j g  t j	 |  j ƒ D] } t j j
 |  j | ƒ ^ ql ƒ n  x= | D]5 } t j ƒ  t j j | ƒ } | | j k  r› t Sq› Wt S(   s=   Return a boolean indicating if the APT sources were modified.iÿÿÿÿ(   t   PackageMonitor(   t    landscape.monitor.packagemonitorRL   R<   R=   R>   t   sources_list_filenamet   appendt   sources_list_directoryt   extendt   listdirt   joint   timet   getmtimet   run_intervalt   TrueR   (   R   RL   t	   filenamest   filenamet   seconds_since_last_change(    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   _apt_sources_have_changedš   s    8c            sk   ˆ  j  j s ˆ  j ƒ  r! d } n d t ˆ  j ƒ f } t ˆ  j d | ƒ} ‡  f d †  } | j | ƒ | S(   s‚   Run smart-update and log a warning in case of non-zero exit code.

        @return: a deferred returning (out, err, code)
        s   --aftert   argsc            sñ   |  \ ‰ ‰ ‰  t  } ˆ  d k r6 ˆ  d k r6 t } n  ˆ  d k r] ˆ j ƒ  d k r] t } n  | rƒ t j d ˆ j ˆ  ˆ f ƒ n  t j d ˆ j ˆ  ˆ ˆ f ƒ t ˆ j j	 ƒ ˆ j
 j d ˆ j ˆ  ˆ ƒ } | j ‡  ‡ ‡ f d †  ƒ | S(   Ni    i   t    s   '%s' exited with status %d (%s)s.   '%s' exited with status %d (out='%s', err='%s's   package-reporter-resultc            s   ˆ ˆ ˆ  f S(   N(    (   t   ignore(   t   codet   errt   out(    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   Ì   s    (   R   RW   t   stripR-   R5   t   smart_update_filenamet   debugR   RA   t   smart_update_stamp_filenamet   _brokert   call_if_acceptedt   send_resultR$   (   t   .0Ra   R`   R_   t   smart_failedt   deferred(   R   (   R_   R`   Ra   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR%   »   s     					(    (   RA   t   force_smart_updateR[   R6   t   smart_update_intervalR   Rc   R$   (   R   R\   R'   R%   (    (   R   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   °   s    	c         C   s.   i d d 6| d 6| d 6} |  j  j | t ƒ S(   sP   
        Report the package reporter result to the server in a message.
        s   package-reporter-resultt   typeR_   R`   (   Rf   t   send_messageRW   (   R   R_   R`   t   message(    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyRh   Ò   s
    
c         C   sD   | j  } | d d k r& |  j | ƒ S| d d k r@ |  j ƒ  Sd  S(   NRn   s   package-idst   resynchronize(   R/   t   _handle_package_idst   _handle_resynchronize(   R   t   taskRp   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   handle_taskÜ   s
    	c            sÿ   g  } y |  j  j | d ƒ ‰  Wn t k
 r: t d  ƒ SXi  } xJ t ˆ  j | d ƒ D]2 \ } } | d  k r€ | j | ƒ qX | | | <qX W|  j  j | ƒ t	 j
 d t | ƒ t | ƒ f ƒ | rÙ |  j | ƒ } n t d  ƒ } | j ‡  f d †  ƒ | S(   Ns
   request-idt   idssC   Received %d package hash => id translations, %d hashes are unknown.c            s
   ˆ  j  ƒ  S(   N(   t   remove(   R   (   t   request(    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   ÿ   s    (   t   _storet   get_hash_id_requestR
   R   R&   t   zipt   hashesRO   t   set_hash_idsR-   R.   t   lent   _handle_unknown_packagesR$   (   R   Rp   t   unknown_hashest   hash_idst   hasht   idR'   (    (   Rx   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyRr   ã   s$    #	c         C   sK   |  j  j ƒ  |  j  j ƒ  |  j  j ƒ  |  j  j ƒ  |  j  j ƒ  t d  ƒ S(   N(   Ry   t   clear_availablet   clear_available_upgradest   clear_installedt   clear_lockedt   clear_package_locksR   R&   (   R   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyRs     s    c   	      C   s<  |  j  j ƒ  t | ƒ } g  } g  } x¾ |  j  j ƒ  D]­ } |  j  j | ƒ } | | k r5 | j | ƒ |  j  j | ƒ } | j i	 | j d 6| j d 6| j	 d 6| j
 d 6| j d 6| j d 6| j d 6| j d 6| j d	 6ƒ q5 q5 W| r,t j d
 t | ƒ ƒ i d d 6| d 6} |  j | | ƒ } n t d  ƒ } | S(   NRn   t   namet   versiont   sectiont   summaryt   descriptiont   sizes   installed-sizet	   relationss@   Queuing messages with data for %d packages to exchange urgently.s   add-packagest   packages(   t   _facadet   ensure_channels_reloadedt   sett   get_packagest   get_package_hashRO   t   get_package_skeletonRn   R‰   RŠ   R‹   RŒ   R   RŽ   t   installed_sizeR   R-   R.   R~   t"   _send_message_with_hash_id_requestR   R&   (	   R   R|   t   added_hashesR   t   packageR‚   t   skeletonRp   R'   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR     s4    






		c            s    t  j  ƒ  ‰ ˆ t ‰  ‡ ‡  f d †  } g  } xe |  j j ƒ  D]T } | j d  k r` | j ƒ  q> |  j j | j ƒ } | j	 | | ƒ | j
 | ƒ q> Wt | ƒ S(   Nc            s2   |  r ˆ  | _  n | j  ˆ k  r. | j ƒ  n  d  S(   N(   t	   timestampRw   (   t
   is_pendingRx   (   t   nowt   timeout(    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   update_or_removeA  s    (   RT   t   HASH_ID_REQUEST_TIMEOUTRy   t   iter_hash_id_requestst
   message_idR&   Rw   Rf   t   is_message_pendingR$   RO   R   (   R   R    t   resultsRx   R'   (    (   RŸ   Rž   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR!   =  s    
c         C   s  |  j  j ƒ  t ƒ  } x] |  j  j ƒ  D]L } |  j  j | ƒ } |  j j | ƒ d k r& | j |  j  j | ƒ ƒ q& q& Wx* |  j j	 ƒ  D] } | t | j
 ƒ 8} q† W| s¸ t d ƒ } nS t | ƒ } | t  } t j d t | ƒ ƒ i d d 6| d 6} |  j | | ƒ } | S(   sº  Detect available packages for which we have no hash=>id mappings.

        This method will verify if there are packages that Smart knows
        about but for which we don't have an id yet (no hash => id
        translation), and deliver a message (unknown-package-hashes)
        to request them.

        Hashes previously requested won't be requested again, unless they
        have already expired and removed from the database.
        sB   Queuing request for package hash => id translation on %d hash(es).s   unknown-package-hashesRn   R|   N(   R‘   R’   R“   R”   R•   Ry   t   get_hash_idR&   t   addR¢   R|   R   t   sortedt   MAX_UNKNOWN_HASHES_PER_REQUESTR-   R.   R~   R˜   (   R   R€   Rš   R‚   Rx   R'   Rp   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR"   W  s&    	 
	

		c            sb   |  j  j | ƒ ‰  ˆ  j | d <|  j j | t ƒ } ‡  f d †  } ‡  f d †  } | j | | ƒ S(   s<   Create a hash_id_request and send message with "request-id".s
   request-idc            s   |  ˆ  _  d  S(   N(   R£   (   R£   (   Rx   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   set_message_id†  s    c            s   ˆ  j  ƒ  |  S(   N(   Rw   (   R7   (   Rx   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   send_message_failed‰  s    
(   Ry   t   add_hash_id_requestRƒ   Rf   Ro   RW   t   addCallbacks(   R   Rp   R€   R'   Rª   R«   (    (   Rx   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR˜   €  s    c            s:   ‡  f d †  } t  ˆ  j ƒ  ˆ  j ƒ  g ƒ } | j | ƒ S(   s×   Detect all changes concerning packages.

        If some changes were detected with respect to our last run, then an
        event of type 'package-data-changed' will be fired in the broker
        reactor.
        c            s-   ˆ  j  j ƒ  t |  k r) ˆ  j j d ƒ Sd  S(   Ns   package-data-changed(   R‘   t   deinitRW   Rf   t
   fire_event(   R¥   (   R   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   changes_detected—  s    (   R   t   detect_packages_changest   detect_package_locks_changesR$   (   R   R°   R'   (    (   R   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR#     s    c            s  ˆ j  j ƒ  t ˆ j j ƒ  ƒ } t ˆ j j ƒ  ƒ } t ˆ j j ƒ  ƒ } t ˆ j j ƒ  ƒ } t ƒ  } t ƒ  } t ƒ  } t ƒ  } xÿ ˆ j  j ƒ  D]î }	 ˆ j  j	 |	 ƒ }
 ˆ j j
 |
 ƒ } | d k	 r• |	 j r| j | ƒ x> |	 j D]# } | j ƒ  së | j | ƒ Pqë që Wn | j | ƒ x^ |	 j D]P } xF | j D]8 } x. | j D]  } | j rL| j | ƒ PqLqLWq<Pq<Wq,Pq,Wq• q• WxW ˆ j  j ƒ  D]F }	 ˆ j  j	 |	 ƒ }
 ˆ j j
 |
 ƒ } | d k	 r—| j | ƒ q—q—W| | ‰ | | ‰ | | ‰ | | ‰ | | ‰ | | ‰ | | ‰ | | ‰  i  } ˆ r\t t t ˆ ƒ ƒ ƒ | d <n  ˆ rt t t ˆ ƒ ƒ ƒ | d <n  ˆ r¦t t t ˆ ƒ ƒ ƒ | d <n  ˆ rËt t t ˆ ƒ ƒ ƒ | d <n  ˆ rðt t t ˆ ƒ ƒ ƒ | d <n  ˆ rt t t ˆ ƒ ƒ ƒ | d <n  ˆ r:t t t ˆ ƒ ƒ ƒ | d <n  ˆ  r_t t t ˆ  ƒ ƒ ƒ | d <n  | sot t ƒ Sd	 | d
 <ˆ j j | t ƒ } t j d t ˆ ƒ t ˆ ƒ t ˆ ƒ t ˆ ƒ t ˆ ƒ t ˆ ƒ t ˆ ƒ t ˆ  ƒ f ƒ ‡  ‡ ‡ ‡ ‡ ‡ ‡ ‡ ‡ f	 d †  } | j | ƒ | S(   s.  Detect changes in the universe of known packages.

        This method will verify if there are packages that:

        - are now installed, and were not;
        - are now available, and were not;
        - are now locked, and were not;
        - were previously available but are not anymore;
        - were previously installed but are not anymore;
        - were previously locked but are not anymore;

        Additionally it will report package locks that:

        - are now set, and were not;
        - were previously set but are not anymore;

        In all cases, the server is notified of the new situation
        with a "packages" message.

        @return: A deferred resulting in C{True} if package changes were
            detected with respect to the previous run, or C{False} otherwise.
        t	   installedt	   availables   available-upgradest   lockeds   not-installeds   not-availables   not-available-upgradess
   not-lockedR   Rn   s»   Queuing message with changes in known packages: %d installed, %d available, %d available upgrades, %d locked, %d not installed, %d not available, %d not available upgrades, %d not locked.c            sÌ   ˆ r ˆ j  j ˆ ƒ n  ˆ r2 ˆ j  j ˆ ƒ n  ˆ rK ˆ j  j ˆ ƒ n  ˆ rd ˆ j  j ˆ ƒ n  ˆ r} ˆ j  j ˆ ƒ n  ˆ r– ˆ j  j ˆ ƒ n  ˆ r¯ ˆ j  j ˆ ƒ n  ˆ  rÈ ˆ j  j ˆ  ƒ n  t	 S(   N(
   Ry   t   add_installedt   remove_installedt   add_availablet
   add_lockedt   remove_availablet   add_available_upgradest   remove_available_upgradest   remove_lockedRW   (   R'   (	   t
   not_lockedt   new_availablet
   new_lockedt   new_upgradesR   t   not_upgradest   not_availablet   new_installedt   not_installed(    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   update_currently_known  s"    N(    R‘   R’   R“   Ry   t   get_installedt   get_availablet   get_available_upgradest
   get_lockedR”   R•   R¦   R&   R³   R§   t   loaderst   getInstalledt   upgradest
   providedbyR   t   get_locked_packagest   listR   R¨   R   R   Rf   Ro   RW   R-   R.   R~   R$   (   R   t   old_installedt   old_availablet   old_upgradest
   old_lockedt   current_installedt   current_availablet   current_upgradest   current_lockedRš   R‚   Rƒ   t   loadert   upgradet   providest   provides_packageRp   R'   RÆ   (    (	   R¾   R¿   RÀ   R   RÂ   RÃ   RÄ   RÁ   RÅ   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR±   ¢  s    						









	'c            sî   t  ˆ j j ƒ  ƒ } t  ˆ j j ƒ  ƒ } | | ‰  | | ‰ i  } ˆ  r] t ˆ  ƒ | d <n  ˆ rv t ˆ ƒ | d <n  | s† t t ƒ Sd | d <ˆ j j | t	 ƒ } t
 j d t ˆ  ƒ t ˆ ƒ f ƒ ‡ ‡  ‡ f d †  } | j | ƒ | S(   sÍ  Detect changes in known package locks.

        This method will verify if there are package locks that:

        - are now set, and were not;
        - were previously set but are not anymore;

        In all cases, the server is notified of the new situation
        with a "packages" message.

        @return: A deferred resulting in C{True} if package lock changes were
            detected with respect to the previous run, or C{False} otherwise.
        t   createdt   deleteds   package-locksRn   sL   Queuing message with changes in known package locks: %d created, %d deleted.c            s6   ˆ r ˆ j  j ˆ ƒ n  ˆ  r2 ˆ j  j ˆ  ƒ n  t S(   N(   Ry   t   add_package_lockst   remove_package_locksRW   (   R'   (   t   unset_package_lockst   set_package_locksR   (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyRÆ   X  s
    (   R“   Ry   t   get_package_locksR‘   R¨   R   R   Rf   Ro   RW   R-   R.   R~   R$   (   R   t   old_package_lockst   current_package_locksRp   R'   RÆ   (    (   Râ   R   Rá   s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR²   4  s$    



	(   R   R   R   R   t   config_factoryt
   queue_nameRm   Rc   RN   RP   R(   R   R?   R[   R   Rh   Ru   Rr   Rs   R   R!   R"   R˜   R#   R±   R²   (    (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyR   &   s.   		7			"	
		 		#		)			’c         C   s   t  t |  ƒ S(   N(   R	   R   (   R\   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   maind  s    c          C   s8   t  j j t  j j t j d ƒ ƒ }  t  j j |  d ƒ S(   Ni    s   landscape-package-reporter(   R<   R=   t   dirnamet   abspatht   syst   argvRS   (   Ré   (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   find_reporter_commandh  s    %(   RI   R-   RT   Rë   R<   t   twisted.internet.deferR    R   t   landscape.lib.sequencerangesR   t   landscape.lib.twisted_utilR   R   t   landscape.lib.fetchR   t   landscape.lib.fsR   t   landscape.package.taskhandlerR   R   R	   t   landscape.package.storeR
   R¡   R©   R   R   Rè   Rí   (    (    (    s>   /usr/lib/python2.7/dist-packages/landscape/package/reporter.pyt   <module>   s&   ÿ ÿ @	