ó
½-'Nc           @   s9  d  d l  Z  d  d l Z d  d l Z d  d l m Z d  d l 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 d	 Z d
 e f Z d e f d „  ƒ  YZ d „  Z d „  Z d e f d „  ƒ  YZ d e f d „  ƒ  YZ d e f d „  ƒ  YZ d „  Z d „  Z e
 d „ Z d S(   iÿÿÿÿN(   t   Deferred(   t   loads(   t   log_failure(   t   fetcht
   FetchError(   t   is_valid_tag_list(   t   get_fqdn(   t   get_vm_infos   169.254.169.254s   http://%s/latestt   InvalidCredentialsErrorc           B   s   e  Z d  Z RS(   s}   
    Raised when an invalid account title and/or registration password
    is used with L{RegistrationManager.register}.
    (   t   __name__t
   __module__t   __doc__(    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR      s   c            s+   ‡  f d †  } ‡  f d †  } t  | | ƒ S(   Nc            s   |  j  j ˆ  ƒ S(   N(   t   _persistt   get(   t   self(   t   name(    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR      s    c            s   |  j  j ˆ  | ƒ d  S(   N(   R   t   set(   R   t   value(   R   (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR      s    (   t   property(   R   R   R   (    (   R   sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   persist_property   s    c            s   ‡  f d †  } t  | ƒ S(   Nc            s   t  |  j ˆ  ƒ S(   N(   t   getattrt   _config(   R   (   R   (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR   '   s    (   R   (   R   R   (    (   R   sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   config_property%   s    t   Identityc           B   s_   e  Z d  Z e d ƒ Z e d ƒ Z e d ƒ Z e d ƒ Z e d ƒ Z	 e d ƒ Z
 d „  Z RS(   s½  Maintains details about the identity of this Landscape client.

    @ivar secure_id: A server-provided ID for secure message exchange.
    @ivar insecure_id: Non-secure server-provided ID, mainly used with
        the ping server.
    @ivar computer_title: See L{BrokerConfiguration}.
    @ivar account_name: See L{BrokerConfiguration}.
    @ivar registration_password: See L{BrokerConfiguration}.
    @ivar tags: See L{BrokerConfiguration}
    s	   secure-ids   insecure-idt   computer_titlet   account_namet   registration_passwordt   tagsc         C   s   | |  _  | j d ƒ |  _ d S(   s½   
        @param config: A L{BrokerConfiguration} object, used to set the
            C{computer_title}, C{account_name} and C{registration_password}
            instance variables.
        t   registrationN(   R   t   root_atR   (   R   t   configt   persist(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   __init__@   s    	(   R	   R
   R   R   t	   secure_idt   insecure_idR   R   R   R   R   R    (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR   -   s   
t   RegistrationHandlerc           B   sk   e  Z d  Z d d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z	 d „  Z
 d „  Z d	 „  Z d
 „  Z RS(   sÉ   
    An object from which registration can be requested of the server,
    and which will handle forced ID changes from the server.

    L{register} should be used to perform initial registration.
    c         C   sâ   | |  _  | |  _ | |  _ | |  _ | |  _ | |  _ |  j j d |  j ƒ |  j j d |  j ƒ |  j j d |  j	 ƒ |  j j
 d |  j ƒ |  j j
 d |  j ƒ |  j j
 d |  j ƒ d  |  _ | |  _ d  |  _ d  |  _ d  S(   Nt   runs   pre-exchanges   exchange-dones   set-ids
   unknown-idR   (   R   t	   _identityt   _reactort	   _exchanget   _pingert   _message_storet   call_ont   _fetch_ec2_datat   _handle_pre_exchanget   _handle_exchange_donet   register_messaget   _handle_set_idt   _handle_unknown_idt   _handle_registrationt   Nonet   _should_registert   _fetch_asynct   _otpt	   _ec2_data(   R   R   t   identityt   reactort   exchanget   pingert   message_storet   fetch_async(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR    R   s"    						
			c         C   sg   |  j  } |  j j r5 t | j o1 |  j j d ƒ ƒ St | j oc | j oc | j oc |  j j d ƒ ƒ S(   Ns   register-cloud-vmt   register(	   R%   R   t   cloudt   boolR!   R)   t   acceptsR   R   (   R   t   id(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   should_registerf   s    	c         C   s;   d |  j _ d |  j _ t |  j ƒ j } |  j j ƒ  | S(   sô   
        Attempt to register with the Landscape server.

        @return: A L{Deferred} which will either be fired with None if
            registration was successful or will fail with an
            L{InvalidCredentialsError} if not.
        N(	   R2   R%   R!   R"   t   RegistrationResponseR&   t   deferredR'   R9   (   R   t   result(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR=   o   s
    c         C   s   |  j  t | ƒ j | j ƒ S(   st   
        Get data at C{path} on the EC2 API endpoint, and add the result to the
        C{accumulate} list.
        (   R4   t   EC2_APIt   addCallbackt   append(   R   t   patht
   accumulate(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt	   _get_data}   s    c            s÷   ˆ  j  } ˆ  j j ró | j ró g  ‰ ˆ  j t d ƒ j t ƒ j ˆ j	 ƒ } d d d d d d d g } x* | D]" } | j | ‡  ‡ f d	 † ƒ qo W| j ‡  f d
 †  ƒ | j ˆ j	 ƒ ‡  ‡ f d †  } d „  } | j | ƒ | j | ƒ n  d S(   sA   Retrieve available EC2 information, if in a EC2 compatible cloud.s
   /user-datas   /meta-data/instance-ids   /meta-data/reservation-ids   /meta-data/local-hostnames   /meta-data/public-hostnames   /meta-data/ami-launch-indexs   /meta-data/kernel-ids   /meta-data/ami-idc            s   ˆ  j  | ˆ ƒ S(   N(   RK   (   t   ignoreRI   (   R   t   ec2_data(    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   <lambda>›   s    c            s   ˆ  j  t d ƒ j t ƒ S(   Ns   /meta-data/ramdisk-id(   R4   RF   t
   addErrbackR   (   RL   (   R   (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyRN   ž   s   c      	      sÐ  ˆ \	 } } } } } } } } }	 i | d 6| d 6| d 6| d 6| d 6| d 6|	 d 6| d 6ˆ  _  xQ ˆ  j  j ƒ  D]@ \ }
 } | d
 k rœ |
 d k rœ qr n  | j d	 ƒ ˆ  j  |
 <qr Wt ˆ  j  d ƒ ˆ  j  d <ˆ  j j rï ˆ  j j ˆ  _ d
 St | t | ƒ ƒ } | d
 k	 rÌ| d ˆ  _ | d } | d } ˆ  j	 j
 j | ƒ ˆ  j j | ƒ | ˆ  j _ | ˆ  j _ d | k r¼d d l m } | ˆ  j | d ƒ } | ˆ  j _ | ˆ  j	 j
 _ n  ˆ  j j ƒ  n  d
 S(   s1   Record the instance data returned by the EC2 API.t   instance_keyt   reservation_keyt   local_hostnamet   public_hostnamet   launch_indext
   kernel_keyt   ramdisk_keyt	   image_keys   utf-8Nt   otps   exchange-urls   ping-urls   ssl-ca-certificateiÿÿÿÿ(   t   store_public_key_data(   R6   t   itemsR2   t   decodet   intR   RX   R5   t   _extract_ec2_instance_dataR'   t
   _transportt   set_urlR(   t   urlt   ping_urlt   landscape.configurationRY   t   ssl_public_keyt   _pubkeyt   write(   RL   t   raw_user_dataRP   RQ   RR   RS   RT   RU   t   ami_keyRV   t   kt   vt   instance_datat   exchange_urlRa   RY   t   public_key_file(   R   RM   (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   record_data¢   sH    !

c         S   s   t  |  d d |  j f ƒd  S(   Nt   msgs&   Got error while fetching meta-data: %r(   R   R   (   t   error(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt	   log_errorÍ   s    N(
   R%   R   R>   R!   R4   RF   RO   R   RG   RH   (   R   RA   RD   t   pathsRI   Rm   Rp   (    (   R   RM   sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR+   „   s,    		+	c         C   s*   |  j  ƒ  r& |  j r& |  j j ƒ  n  d S(   sM  Registered handler for the C{"exchange-done"} event.

        If we are not registered yet, schedule another message exchange.

        The first exchange made us accept the message type "register", so
        the next "pre-exchange" event will make L{_handle_pre_exchange}
        queue a registration message for delivery.
        N(   RB   R3   R'   R9   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR-   Ô   s    	c         C   sl  |  j  ƒ  |  _ |  j rh|  j } |  j j ƒ  | j } t | ƒ sY d } t j	 d ƒ n  |  j
 j r£|  j d k	 r£|  j rí t j d ƒ i d d 6|  j d 6t ƒ  d 6d d 6d d 6| d	 6t ƒ  d
 6} | j |  j ƒ |  j j | ƒ qe| j rd d | g t | ƒ } t j d | j | f ƒ i d d 6d d 6t ƒ  d 6| j d 6| j d 6| d	 6t ƒ  d
 6} | j |  j ƒ |  j j | ƒ qe|  j j d ƒ qh| j rUd d g t | j ƒ } d d | g t | ƒ } t j d | j | | f ƒ i d d 6| j d 6| j d 6| j d 6t ƒ  d 6| d	 6t ƒ  d
 6} |  j j | ƒ qh|  j j d ƒ n  d S(   sÈ   
        An exchange is about to happen.  If we don't have a secure id already
        set, and we have the needed information available, queue a registration
        message with the server.
        s-   Invalid tags provided for cloud registration.s%   Queueing message to register with OTPs   register-cloud-vmt   typeRX   t   hostnameR   R   R   s   vm-infot    u   and tags %s uB   Queueing message to register with account %r %sas an EC2 instance.s   registration-failedt   withoutt   withu=   Queueing message to register with account %r %s%s a password.R=   R   N(   RB   R3   R%   R)   t   delete_all_messagesR   R   R2   t   loggingRo   R   R>   R6   R5   t   infoR   R   t   updateR'   t   sendR   R?   R   R&   t   fireR   (   R   RA   R   t   messaget	   with_tagst	   with_word(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR,   à   sd    				


	



			




c         C   s   |  j  } | j d ƒ | _ | j d ƒ | _ t j d | j d | j ƒ t j d | j ƒ |  j j	 d ƒ |  j j	 d ƒ d S(	   s×   Registered handler for the C{"set-id"} event.

        Record and start using the secure and insecure IDs from the given
        message.

        Fire C{"registration-done"} and C{"resynchronize-clients"}.
        RA   s   insecure-ids2   Using new secure-id ending with %s for account %s.iöÿÿÿs   Using new secure-id: %ss   registration-dones   resynchronize-clientsN(
   R%   R   R!   R"   Rx   Ry   R   t   debugR&   R|   (   R   R}   RA   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR/   #  s    		c         C   s'   | d d k r# |  j  j d ƒ n  d  S(   NRy   s   unknown-accounts   registration-failed(   R&   R|   (   R   R}   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR1   4  s    c         C   s3   |  j  } t j d | j ƒ d  | _ d  | _ d  S(   Ns,   Client has unknown secure-id for account %s.(   R%   Rx   Ry   R   R2   R!   R"   (   R   R}   RA   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR0   8  s
    			N(   R	   R
   R   R2   R    RB   R=   RK   R+   R-   R,   R/   R1   R0   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR#   J   s   					P		C		RC   c           B   s2   e  Z d  Z d „  Z d „  Z d „  Z d „  Z RS(   sµ   A helper for dealing with the response of a single registration request.

    @ivar deferred: The L{Deferred} that will be fired as per
        L{RegistrationHandler.register}.
    c         C   sI   | |  _  | j d |  j ƒ |  _ | j d |  j ƒ |  _ t ƒ  |  _ d  S(   Ns   registration-dones   registration-failed(   R&   R*   t   _donet   _done_idt   _failedt
   _failed_idR    RD   (   R   R8   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR    G  s    	c         C   s*   |  j  j |  j ƒ |  j  j |  j ƒ d  S(   N(   R&   t   cancel_callR‚   R„   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   _cancel_callsM  s    c         C   s   |  j  j d  ƒ |  j ƒ  d  S(   N(   RD   t   callbackR2   R†   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR   Q  s    c         C   s!   |  j  j t ƒ  ƒ |  j ƒ  d  S(   N(   RD   t   errbackR   R†   (   R   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyRƒ   U  s    (   R	   R
   R   R    R†   R   Rƒ   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyRC   @  s
   			c         C   s  y t  |  ƒ } Wn& t k
 r8 t j d |  f ƒ d SXt | t ƒ s` t j d | f ƒ d Sx5 d D]- } | | k rg t j d | | f ƒ d Sqg Wt | d ƒ | k rÉ t j d | | f ƒ d Si | d | d	 6| d d 6| d d 6} d
 | k r| d
 | d
 <n  | S(   sà   
    Given the raw string of EC2 User Data, parse it and return the dict of
    instance data for this particular instance.

    If the data can't be parsed, a debug message will be logged and None
    will be returned.
    s   Got invalid user-data %rNs   user-data %r is not a dictt   otpss   exchange-urls   ping-urls!   user-data %r doesn't have key %r.s1   user-data %r doesn't have OTP for launch index %dRX   s   ssl-ca-certificate(   R‰   s   exchange-urls   ping-url(   R   t
   ValueErrorRx   R€   t
   isinstancet   dictt   len(   Rf   RT   t	   user_datat   keyRj   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyR]   Z  s.    		c          C   s˜   d }  d } t  j  ƒ  } xy t r“ t j ƒ  } y% | j t | f ƒ | j ƒ  d SWq t j k
 r t  j d ƒ t  j  ƒ  | |  k r Pq q Xq Wd S(   s0  
    Keep trying to connect to the EC2 metadata server until it becomes
    accessible or until five minutes pass.

    This is necessary because the networking init script on Ubuntu is
    asynchronous; the network may not actually be up by the time the
    landscape-client init script is invoked.
    i   i<   iP   Ni   i,  (   t   timet   Truet   sockett   connectt   EC2_HOSTt   closeRo   t   sleep(   t   timeoutt   portt   startt   s(    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   _wait_for_network|  s    		
c         C   sk   t  ƒ  y0 |  t d d d ƒ} |  t d d d ƒ} Wn t k
 rK t SXt | t | ƒ ƒ } | d k	 S(   s   
    Return C{True} if the machine has been started by Landscape, i.e. if we can
    find the expected data inside the EC2 user-data field.
    s
   /user-datat   connect_timeouti   s   /meta-data/ami-launch-indexN(   R›   RF   R   t   FalseR]   R\   R2   (   R   Rf   RT   Rj   (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   is_cloud_managed•  s    	(   R   Rx   R’   t   twisted.internet.deferR    t   landscape.lib.bpickleR   t   landscape.lib.logR   t   landscape.lib.fetchR   R   t   landscape.lib.tagR   t   landscape.lib.networkR   t   landscape.lib.vm_infoR   R”   RF   t	   ExceptionR   R   R   t   objectR   R#   RC   R]   R›   Rž   (    (    (    sA   /usr/lib/python2.7/dist-packages/landscape/broker/registration.pyt   <module>   s(   		ö	"	