ó
½-'Nc           @   s*  d  d l  Z  d  d l Z d  d l Z d  d l m Z m 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 m Z d  d l m Z m Z d  d	 l m Z d
 e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d d „ Z d S(   iÿÿÿÿN(   t   succeedt   Deferred(   t	   lock_patht	   LockError(   t   log_failure(   t   LSB_RELEASE_FILENAMEt   parse_lsb_release(   t   TwistedReactor(   t   Configurationt   init_logging(   t   PackageStoret   InvalidHashIdDb(   t   RemoteBrokerConnectort   PackageTaskErrorc           B   s   e  Z d  Z RS(   s6   Raised when a task hasn't been successfully completed.(   t   __name__t
   __module__t   __doc__(    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR      s   t   PackageTaskHandlerConfigurationc           B   sJ   e  Z d  Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z e d „  ƒ Z RS(   s5   Specialized configuration for L{PackageTaskHandler}s.c         C   s   t  j j |  j d ƒ S(   s&   Get the path to the package directory.t   package(   t   ost   patht   joint	   data_path(   t   self(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   package_directory   s    c         C   s   t  j j |  j d ƒ S(   s8   Get the path to the SQlite file for the L{PackageStore}.t   database(   R   R   R   R   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   store_filename   s    c         C   s   t  j j |  j d ƒ S(   s?   Get the path to the directory holding the stock hash-id stores.s   hash-id(   R   R   R   R   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   hash_id_directory!   s    c         C   s   t  j j |  j d ƒ S(   s,   Get the path to the smart-update stamp file.s   smart-update-stamp(   R   R   R   R   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   smart_update_stamp_filename&   s    (   R   R   R   t   propertyR   R   R   R   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR      s
   t   LazyRemoteBrokerc           B   s    e  Z d  Z d „  Z d „  Z RS(   s  Wrapper class around L{RemoteBroker} providing lazy initialization.

    This class is a wrapper around a regular L{RemoteBroker}. It connects to
    the remote broker object only when one of its attributes is first accessed.

    @param connector: The L{RemoteBrokerConnector} which will be used
        to connect to the broker.

    @note: This behaviour is needed in particular by the ReleaseUpgrader and
        the PackageChanger, because if the they connect early and the
        landscape-client package gets upgraded while they run, they will lose
        the connection and will not be able to reconnect for a potentially long
        window of time (till the new landscape-client package version is fully
        configured and the service is started again).
    c         C   s   | |  _  d  |  _ d  S(   N(   t
   _connectort   Nonet   _remote(   R   t	   connector(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   __init__=   s    	c            s/   ˆ  j  r t ˆ  j  ˆ ƒ S‡  ‡ f d †  } | S(   Nc             s4   ‡ ‡  ‡ ‡ f d †  } ˆ j  j ƒ  } | j | ƒ S(   Nc            s"   |  ˆ  _  t ˆ  j  ˆ ƒ ˆ ˆ Ž  S(   N(   R!   t   getattr(   t   remote(   R   t   argst   kwargst   method(    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   got_connectionH   s    	(   R   t   connectt   addCallback(   R&   R'   R)   t   result(   R   R(   (   R&   R'   sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   wrapperF   s    (   R!   R$   (   R   R(   R-   (    (   R   R(   sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   __getattr__A   s    		(   R   R   R   R#   R.   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR   ,   s   	t   PackageTaskHandlerc           B   st   e  Z e Z d  Z e Z d „  Z d „  Z d „  Z	 d
 d „ Z d „  Z d „  Z e d „  ƒ Z d „  Z d	 „  Z RS(   t   defaultc         C   s1   | |  _  | |  _ | |  _ | |  _ d |  _ d  S(   Ni    (   t   _storet   _facadet   _brokert   _configt   _count(   R   t   package_storet   package_facadet   remote_brokert   config(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR#   Y   s
    				c         C   s
   |  j  ƒ  S(   N(   t   handle_tasks(   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   run`   s    c         C   s   |  j  d ƒ S(   s¼   Handle the tasks in the queue.

        The tasks will be handed over one by one to L{handle_task} until the
        queue is empty or a task fails.

        @see: L{handle_tasks}
        N(   t   _handle_next_taskR    (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR:   c   s    c         C   sŠ   | d k	 r( | j ƒ  |  j d 7_ n  |  j j |  j ƒ } | r| |  j | ƒ } | j |  j d | ƒ| j	 |  j
 ƒ | St d ƒ Sd S(   s@   Pick the next task from the queue and pass it to C{handle_task}.i   t	   last_taskN(   R    t   removeR5   R1   t   get_next_taskt
   queue_namet   handle_taskR+   R<   t
   addErrbackt   _handle_task_failureR    (   R   R,   R=   t   task(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR<   m   s    
c         C   s   | j  t ƒ d S(   s@   Gracefully handle a L{PackageTaskError} and stop handling tasks.N(   t   trapR   (   R   t   failure(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyRC   ‚   s    c         C   s
   t  d ƒ S(   s  Handle a single task.

        Sub-classes must override this method in order to trigger task-specific
        actions.

        This method must return a L{Deferred} firing the task result. If the
        deferred is successful the task will be removed from the queue and the
        next one will be picked. If the task can't be completed, this method
        must raise a L{PackageTaskError}, in this case the handler will stop
        processing tasks and the failed task won't be removed from the queue.
        N(   R    R    (   R   RD   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyRA   †   s    c         C   s   |  j  S(   sX   
        Return the number of tasks that have been successfully handled so far.
        (   R5   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   handled_tasks_count”   s    c            s,   ‡  f d †  } ˆ  j  ƒ  } | j | ƒ | S(   sS   
        Attach the appropriate pre-canned hash=>id database to our store.
        c            sq   |  d  k r d  St j j |  ƒ s& d  Sy ˆ  j j |  ƒ Wn0 t k
 rl t j d |  ƒ t j	 |  ƒ d  SXd  S(   Ns   Invalid hash=>id database %s(
   R    R   R   t   existsR1   t   add_hash_id_dbR   t   loggingt   warningR>   (   t   hash_id_db_filename(   R   (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   use_it    s    	(   t   _determine_hash_id_db_filenameR+   (   R   RM   R,   (    (   R   sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   use_hash_id_db›   s    c            s/   ‡  f d †  } ˆ  j  j ƒ  } | j | ƒ | S(   s§   Build up the filename of the hash=>id database to use.

        @return: a deferred resulting in the filename to use or C{None}
            in case of errors.
        c            sù   d } |  d  k r' t j | d ƒ d  Sy t ˆ  j ƒ } Wn+ t k
 rg } t j | t | ƒ ƒ d  SXy | d } Wn* t k
 r¢ t j | d ˆ  j ƒ d  SXˆ  j j	 ƒ  } | d  k rÓ t j | d ƒ d  St
 j j ˆ  j j d |  | | f ƒ S(   Ns5   Couldn't determine which hash=>id database to use: %ss   server UUID not availables	   code-names   missing code-name key in %ss   unknown dpkg architectures   %s_%s_%s(   R    RJ   RK   R   t   lsb_release_filenamet   IOErrort   strt   KeyErrorR2   t   get_archR   R   R   R4   R   (   t   server_uuidRK   t   lsb_release_infot   errort   codenamet   arch(   R   (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   got_server_uuidÁ   s*    (   R3   t   get_server_uuidR+   (   R   RZ   R,   (    (   R   sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyRN   º   s    N(   R   R   R   t   config_factoryR@   R   RP   R#   R;   R:   R    R<   RC   RA   R   RG   RO   RN   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyR/   R   s   			
			c            s  ˆ  d  k r t ƒ  ‰  n  |  j ƒ  } | j | ƒ x< | j | j g D]( } t j j | ƒ sD t j	 | ƒ qD qD W|  j
 } t j j | j | d ƒ } y t | ƒ Wn6 t k
 rÛ | j rÈ t ƒ  ‚ n  t d | ƒ ‚ n Xt j d |  j ƒ } t | d j d „  | Dƒ ƒ ƒ t j d ƒ d d l m } t | j ƒ }	 | ƒ  }
 ‡ ‡  f d	 †  ‰ ‡ f d
 †  } t ˆ  | d t ƒ‰ t ˆ ƒ } |  |	 |
 | | ƒ ‰ t ƒ  ‰ ˆ j ‡ f d †  ƒ ˆ j ‡ f d †  ƒ ˆ j | ƒ ˆ  j ‡ f d †  ƒ ˆ  j  ƒ  ˆ S(   Ns   .locks$   error: package %s is already runnings   [A-Z][a-z]+t   -c         s   s   |  ] } | j  ƒ  Vq d  S(   N(   t   lower(   t   .0t   word(    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pys	   <genexpr>þ   s    i   iÿÿÿÿ(   t   SmartFacadec              s$   ˆ  j  ƒ  ˆ j d ˆ j j ƒ d  S(   Ni    (   t
   disconnectt
   call_latert   _reactort   stop(    (   R"   t   reactor(    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   finish  s    
c            s   t  |  ƒ ˆ  ƒ  d  S(   N(   R   (   RF   (   Rg   (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt	   got_error  s    
t   retry_on_reconnectc            s
   ˆ  j  ƒ  S(   N(   R;   (   t   x(   t   handler(    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   <lambda>  s    c            s   ˆ  ƒ  S(   N(    (   Rj   (   Rg   (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyRl     s    c              s   ˆ  j  d  ƒ S(   N(   t   callbackR    (    (   R,   (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyRl     s    (!   R    R   R\   t   loadR   R   R   R   t   isdirt   mkdirR@   R   R   R   t   quiett
   SystemExitt   ret   findallR   R	   t   umaskt   landscape.package.facadeRa   R
   R   R   t   TrueR   R   R+   RB   t   call_when_runningR;   (   t   clsR&   Rf   R9   t	   directoryt   program_namet   lock_filenamet   wordsRa   R6   R7   Rh   R%   (    (   Rf   R,   R"   Rk   Rg   sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   run_task_handlerå   sF    		 		
(    R   Rs   RJ   t   twisted.internet.deferR    R   t   landscape.lib.lockR   R   t   landscape.lib.logR   t   landscape.lib.lsb_releaseR   R   t   landscape.reactorR   t   landscape.deploymentR   R	   t   landscape.package.storeR
   R   t   landscape.broker.ampR   t	   ExceptionR   R   t   objectR   R/   R    R~   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/package/taskhandler.pyt   <module>   s   &“