
    x[h:                        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 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mZ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  ej@                  e!      Z"ddgZ#dZ$dZ%dZ& G d dejN                  jP                        Z)d Z*d Z+ G d dejX                        Z-e-ej\                  ffgZ/d Z0y)    N)urlparse)ConnectionError)HTTPConnection)PoolManager)dmiperformancesources
url_helperutil)
EventScope	EventType)NoDHCPLeaseError)EphemeralDHCPv4EphemeralIPv6Network)DataSourceHostname)ProcessExecutionErrorzhttp://169.254.42.42zhttp://[fd00:42::42]      
   c                   *     e Zd ZdZ fdZddZ xZS )SourceAddressAdapterzF
    Adapter for requests to choose the local address to bind to.
    c                 :    || _         t        t        |   di | y )N )source_addresssuperr   __init__)selfr   kwargs	__class__s      F/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceScaleway.pyr   zSourceAddressAdapter.__init__+   s    ,"D2<V<    c                     t         j                  t        j                  t        j                  dfgz   }t        |||| j                  |      | _        y )N   )	num_poolsmaxsizeblockr   socket_options)r   default_socket_optionssocket
SOL_SOCKETSO_REUSEPORTr   r   poolmanager)r   connectionsr%   r&   r'   s        r    init_poolmanagerz%SourceAddressAdapter.init_poolmanager/   sR    '>> 3 3Q7B
 
 '!..)
r!   )F)__name__
__module____qualname____doc__r   r.   __classcell__r   s   @r    r   r   &   s    =

r!   r   c                     	 t        j                  | d|d|d       }t        j                  |j                        S # t         j
                  $ r}|j                  dk(  rY d}~y d}~ww xY w)aQ  
    Retrieve user data or vendor data.

    Scaleway user/vendor data API returns HTTP/404 if user/vendor data is not
    set.

    This function calls `url_helper.readurl` but instead of considering
    HTTP/404 as an error that requires a retry, it considers it as empty
    user/vendor data.

    Also, be aware the user data/vendor API requires the source port to be
    below 1024 to ensure the client is root (since non-root users can't bind
    ports below 1024). If requests raises ConnectionError (EADDRINUSE), the
    caller should retry to call this function on an other port.
    Nr   c                     | j                   dk7  xr/ t        | j                  t        j                  j
                         S )N  )code
isinstancecauserequests
exceptionsr   )excs    r    <lambda>z%query_data_api_once.<locals>.<lambda>W   s3    SXX_ &syy(*=*=*M*MNN r!   )datatimeoutretriessessionexception_cbr7   )r
   readurlr   decode_binarycontentsUrlErrorr8   )api_addressr@   requests_sessionrespr=   s        r    query_data_api_oncerK   <   sk     !! $
 !!$--00 88s?	s   := A*A%$A%%A*c                    t        dt        |d            D ]  }	 t        j                  d| |       t	        j
                         }d}	 t        |      j                  }|}|d   dk(  r|dd }t        j                  |dt        j                  	      d   d   }	|	t        j                  k(  rd
}|j                  dt        ||f             t        |||      }
t        j                  d|        |
c S  # t        $ r Y Tw xY w# t         j"                  $ r9}t        j%                  d| |       t'        j(                  d       |}Y d}~6d}~ww xY w)a/  Get user or vendor data.

    Handle the retrying logic in case the source port is used.

    Scaleway metadata service requires the source port of the client to
    be a privileged port (<1024).  This is done to ensure that only a
    privileged user on the system can access the metadata service.
    r#   r   z*Trying to get %s data (bind on port %d)...z0.0.0.0r   [N)protoz0::zhttp://)r   )r@   rI   z%s-data downloadedz%Error while trying to get %s data: %s   )rangemaxLOGdebugr;   Sessionr   netlocr)   getaddrinfoIPPROTO_TCPAF_INET6
ValueErrormountr   rK   r
   rG   warningtimesleep)api_typerH   rA   r@   portrI   	localhosturl_addressaddress
addr_protor?   r=   last_excs                r    query_data_apirf   d   sa    aWa) #"	II<h  (//1!I&{3::%q>S()!B/G#//T););
 0 %I ""$Y4EF 'W?OD II*H5K9#L N)   "" 	KK?3OJJqMH	s=   -D	A%C7.AD7	D DDDE.EEc                   
    e Zd ZdZej
                  ej                  ej                  ej                  hiZ
 fdZdeddf fdZd Zd Zed	        Zd
 Zed        Zed        Zd Zd ZddZed        Zed        Z xZS )DataSourceScalewayScalewayc                    t         t        |   |||       t        j                  t        j
                  |ddgi       g      | _        t        | j                  j                  dt                    | _
        t        | j                  j                  dt                    | _        t        | j                  j                  dt                    | _        t        j                   | _        t$        | _        d | _        d | _        d | _        d | _        d| _        d| j                  j3                         v r#| xj&                  | j                  d   z  c_        y y )N
datasourceri   rA   r@   max_waitTmetadata_urls)r   rh   r   r   mergemanydictget_cfg_by_pathds_cfgintgetDEF_MD_RETRIESrA   DEF_MD_TIMEOUTr@   DEF_MD_MAX_WAITrl   r	   UNSET_network_configDS_BASE_URLSrm   metadata_urluserdata_urlvendordata_urlephemeral_fixed_addresshas_ipv4keys)r   sys_cfgdistropathsr   s       r    r   zDataSourceScaleway.__init__   s    $0&%H(($$W|Z.H"M
 4;;??9nEF4;;??9nEFDKKOOJHI&}})  "'+$dkk..00$++o">> 1r!   ci_pkl_versionreturnNc                     t         |   |       d dt        t        d d d}|D ]  }t	        | |      rt        | |||          ! y )NT)r|   r}   rl   rm   rz   r{   )r   	_unpickleru   rx   hasattrsetattr)r   r   attr_defaultsattrr   s       r    r   zDataSourceScaleway._unpickle   sU    .)'+') "
 " 	9D4&dM$$78	9r!   c                 n   t        j                         }t        j                  || j                  | j
                  d      \  }}|r5t        j                  d|       | d| _        | d| _	        | d| _
        yt        j                  d|t        t        j                         |z
               t        )	zO
        Define metadata_url based upon api-metadata URL availability.
        F)urlsrl   r@   connect_synchronouslyz%s is reachablez/conf?format=jsonz/user_data/cloud-initz/vendor_data/cloud-initNz3Unable to reach api-metadata at %s after %s seconds)r]   	monotonicr
   wait_for_urlrl   r@   rS   rT   ry   rz   r{   rq   r   )r   r   
start_time	avail_url_s        r    _set_metadata_urlz$DataSourceScaleway._set_metadata_url   s    
 ^^%
!..]]LL"'	
	1 II'3#,+-> ?D#,+-B CD%.K/F"GDIIEDNN$z12
 "!r!   c                    t        j                  | j                  | j                  | j                        }t        j                  t        j                  |j                              | _
        t        d| j                  | j                  | j                        | _        t        d| j                  | j                  | j                        | _        y )N)r@   rA   z	user-datazvendor-data)r
   rD   ry   r@   rA   jsonloadsr   rE   rF   metadatarf   rz   userdata_rawr{   vendordata_raw)r   rJ   s     r    _crawl_metadataz"DataSourceScaleway._crawl_metadata   s    !!t||T\\
 

4#5#5dmm#DE***DLL$,,
 -4..dll
r!   c                      t        j                  d      } | dk(  ryt        j                  j	                  d      ryt        j                         }d|v ryy)a   
        There are three ways to detect if you are on Scaleway:

        * check DMI data: not yet implemented by Scaleway, but the check is
          made to be future-proof.
        * the initrd created the file /var/run/scaleway.
        * "scaleway" is in the kernel cmdline.
        zsystem-manufacturerri   Tz/var/run/scalewayscalewayN)r   read_dmi_dataospathexistsr   get_cmdline)vendor_namecmdlines     r    	ds_detectzDataSourceScaleway.ds_detect   sR     ''(=>*$77>>-.""$  !r!   c                    | j                   r	 t        | j                  | j                  j                        5 }t	        j
                  d      5  | j                  | j                         d d d        | j                          |d   | _	        d| j                  d<   d d d        | j                   s	 t%        | j                  | j                  j                        5  t	        j
                  d      5  | j                  | j                         d d d        | j                          d| j                  d<   d d d        yy# 1 sw Y   xY w# 1 sw Y   xY w# t        t        t        f$ r4}t        j                  t         t#        |             d| _         Y d }~d }~ww xY w# 1 sw Y   xY w# 1 sw Y   yxY w# t        $ r Y yw xY w)	Nz7Setting api-metadata URL depending on IPv4 availabilityzfixed-addressipv4
net_in_useFz7Setting api-metadata URL depending on IPv6 availabilityipv6T)r}   r   r   fallback_interfacer   Timedr   rm   r   r|   r   r   r   r   r   logexcrS   strr   )r   r   es      r    	_get_datazDataSourceScaleway._get_data  s   
 ==& %KKKK22 9 $**9 C ..t/A/AB	C
 ((*373HD028DMM,/9. }})KKKK22 
9 %**, C ..t/A/AB	C
 ((*28DMM,/
9 EC C	9 9 !% &
 CQ( !&&"C C	
9  # s   *E E	D=*1E	E 0*F8 F,0F 'F,3F8 =E	E		EE F)*FF F)	%F,,F51F8 5F8 8	GGc           	      R   | j                   9t        j                  dt        j                         t        j                  | _         | j                   t        j                  k7  r| j                   S | j
                  d   i }i }| j
                  d   D ]  }|d   | j                  k(  r3d|d<   dddd	}d
|j                         v r|d
xx   |gz  cc<   A|g|d
<   Hd|j                         v r|dxx   |d    d|d    fz  cc<   n|d    d|d    f|d<   |d   dk(  s|d   dd}d
|j                         v r|d
xx   |gz  cc<   |g|d
<    ||| j                  j                  <   d|d| _         ndd| j                  j                  z  d}ddig}| j
                  d   rI|dd| j
                  d   d   z  d| j
                  d   d   z  ddd| j
                  d   d   z  dgdgz  }||d<   d |gd!| _         t        j                  d"| j                          | j                   S )#z`
        Configure networking according to data received from the
        metadata API.
        z5Found None as cached _network_config. Resetting to %s
private_ip
public_ipsrc   Tdhcp4z169.254.42.42/32z
62.210.0.1)zon-linktoviaroutes	addresses/netmaskfamilyinet6gatewayz::/0)r   r   r   )version	ethernetsphysicalz%s)typenamer   r   staticz::0)networkprefixr   )r   rc   r   r   subnetsr#   )r   configznetwork_config : %s)rw   rS   r\   r	   rv   r   r|   r~   r   r   rT   )r   netcfgip_cfgiprouter   s         r    network_configz!DataSourceScaleway.network_config4  s    'KKG $+==D 7==0'''==&. FFmmL1 7i=D$@$@@&*F7O $(0+E
  6;;=0x(UG3(,17x("fkkm3{+!)}oQr)}o>0 +
  ")}oQr)}o>/{+ (|w.(*9V D#v{{}4"8,7,05wF8,97: 6<F4;;112/0v#FD  #t{{===F ()G}}V$ (#'$--*?	*J#J#'$--*?	*J#J ,0*-+/"&--"7	"B,C#	  !(F9/0VH#ED 		')=)=>###r!   c                      y Nr   r   s    r    launch_indexzDataSourceScaleway.launch_index      r!   c                      | j                   d   S )Nid)r   r   s    r    get_instance_idz"DataSourceScaleway.get_instance_id  s    }}T""r!   c                    | j                   d   D cg c]  }|d   	 }}d}t        |      }| j                   j                  dg       D ]8  }|j                  |      s|j	                  ||d  j                  dd             : |S c c}w )Nssh_public_keyskeyzAUTHORIZED_KEY=tagsr    )r   lenrr   
startswithappendreplace)r   r   ssh_keysakeypreplentags         r    get_public_ssh_keysz&DataSourceScaleway.get_public_ssh_keys  s    *.--8I*JK3CJKK#7|==$$VR0 	:C>>'*OOCJ..sC89	:
  Ls   Bc                 4    t        | j                  d   d      S )NhostnameF)r   r   )r   fqdn
resolve_ipmetadata_onlys       r    get_hostnamezDataSourceScaleway.get_hostname  s    !$--
";UCCr!   c                      y r   r   r   s    r    availability_zonez$DataSourceScaleway.availability_zone  r   r!   c                      y r   r   r   s    r    regionzDataSourceScaleway.region  r   r!   )FFF)r/   r0   r1   dsnamer   NETWORKr   BOOT_NEW_INSTANCEBOOTBOOT_LEGACYdefault_update_eventsr   rq   r   r   r   staticmethodr   r   propertyr   r   r   r   r   r   r   r3   r4   s   @r    rh   rh      s    F''NN!!
?,9 9 9"4
  (0d M$ M$^  #
D    r!   rh   c                 6    t        j                  | t              S r   )r	   list_from_dependsdatasources)dependss    r    get_datasource_listr     s    $$Wk::r!   )1r   loggingr   r)   r]   urllib.parser   r;   requests.exceptionsr   urllib3.connectionr   urllib3.poolmanagerr   	cloudinitr   r   r	   r
   r   cloudinit.eventr   r   cloudinit.net.dhcpr   cloudinit.net.ephemeralr   r   cloudinit.sourcesr   cloudinit.subpr   	getLoggerr/   rS   rx   rs   ru   rt   adaptersHTTPAdapterr   rK   rf   
DataSourcerh   DEP_FILESYSTEMr   r   r   r!   r    <module>r     s      	   !  / . + A A 1 / I 0 0g!&(>?
8,,88 
,%P1hH++ HX '0023
;r!   