
"T`&                 @   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 d  d l m Z d  d l	 m
 Z
 d  d l	 m Z d  d l	 m 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 e j e  Z d Z d e d d e d d e d i Z d Z d Z d d   Z Gd d   d e j j  Z  d d   Z! d d   Z" Gd d   d e j#  Z$ e$ e j% f f g Z& d d    Z' d S)!    N)HTTPConnection)PoolManager)dmi)log)sources)
url_helper)util)net)EphemeralDHCPv4NoDHCPLeaseError)	EventTypezhttp://169.254.42.42metadata_urlz/conf?format=jsonuserdata_urlz/user_data/cloud-initvendordata_urlz/vendor_data/cloud-init   
   c              C   sU   t  j d  }  |  d k r d St j j d  r5 d St j   } d | k rQ d Sd S)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-manufacturerScalewayTz/var/run/scalewayZscalewayF)r   Zread_dmi_dataospathexistsr   Zget_cmdline)Zvendor_nameZcmdline r   F/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceScaleway.pyon_scaleway3   s    	r   c                   s7   e  Z d  Z d Z   f d d   Z d d d  Z   S)SourceAddressAdapterzF
    Adapter for requests to choose the local address to bind to.
    c                s#   | |  _  t t |   j |   d  S)N)source_addresssuperr   __init__)selfr   kwargs)	__class__r   r   r   N   s    	zSourceAddressAdapter.__init__Fc             C   sP   t  j t j t j d f g } t d | d | d | d |  j d |  |  _ d  S)N   Z	num_poolsmaxsizeblockr   socket_options)r   Zdefault_socket_optionssocketZ
SOL_SOCKETZSO_REUSEPORTr   r   Zpoolmanager)r   Zconnectionsr!   r"   r#   r   r   r   init_poolmanagerR   s    	z%SourceAddressAdapter.init_poolmanager)__name__
__module____qualname____doc__r   r%   r   r   )r   r   r   J   s   r   c             C   s   yG t  j |  d d d | d d d | d d d	   } t j | j  SWn> t  j k
 r } z | j d
 k rr d S  WYd d } ~ Xn Xd S)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.
    dataNtimeoutretriesr   ZsessionZexception_cbc             S   s&   | j  d k o% t | j t j j  S)Ni  )code
isinstancecauserequests
exceptionsConnectionError)_excr   r   r   <lambda>x   s   z%query_data_api_once.<locals>.<lambda>i  )r   readurlr   decode_binarycontentsUrlErrorr-   )api_addressr+   requests_sessionrespr4   r   r   r   query_data_api_once]   s    r=   c       	      C   s   x t  d t | d   D] } yn t j d |  |  t j   } | j d t d d | f   t | d | d | } t j d	 |   | SWq t	 j
 k
 r } z. t j d
 |  |  t j d  | } w WYd d } ~ Xq Xq W|  d S)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       z*Trying to get %s data (bind on port %d)...zhttp://r   z0.0.0.0r+   r;   z%s-data downloadedz%Error while trying to get %s data: %sr   N)rangemaxLOGdebugr0   ZSessionZmountr   r=   r   r9   warningtimeZsleep)	Zapi_typer:   r,   r+   Zportr;   r*   r4   last_excr   r   r   query_data_api   s*    
	rF   c                   s   e  Z d  Z d Z d e j e j g i Z   f d d   Z d d   Z	 d d   Z
 e d	 d
    Z e d d    Z d d   Z d d   Z d d d d d  Z e d d    Z e d d    Z   S)DataSourceScalewayr   Znetworkc                s   t  t |   j | | |  t j t j | d d g i   t g  |  _ |  j d |  _ |  j d |  _	 |  j d |  _
 t |  j j d t   |  _ t |  j j d t   |  _ d  |  _ t j |  _ d  S)NZ
datasourcer   r   r   r   r,   r+   )r   rG   r   r   ZmergemanydictZget_cfg_by_pathBUILTIN_DS_CONFIGZds_cfgmetadata_addressuserdata_addressvendordata_addressintgetDEF_MD_RETRIESr,   DEF_MD_TIMEOUTr+   _fallback_interfacer   UNSET_network_config)r   Zsys_cfgZdistropaths)r   r   r   r      s    	zDataSourceScaleway.__init__c             C   s   t  j |  j d |  j d |  j } t j t j | j	   |  _
 t d |  j |  j |  j  |  _ t d |  j |  j |  j  |  _ d  S)Nr+   r,   z	user-datazvendor-data)r   r6   rI   r+   r,   jsonloadsr   r7   r8   metadatarF   rJ   Zuserdata_rawrK   Zvendordata_raw)r   r<   r   r   r   _crawl_metadata   s    			z"DataSourceScaleway._crawl_metadatac             C   s   t    s d S|  j d  k r+ t j   |  _ y= t |  j  ' t j d t j d d d |  j	  Wd  QRXWn? t
 k
 r } z t j t t |   d SWYd  d  } ~ Xn Xd S)NFZlogfuncmsgzCrawl of metadata servicefuncT)r   rP   r	   find_fallback_nicr
   r   Zlog_timerA   rB   rW   r   Zlogexcstr)r   er   r   r   	_get_data   s    		zDataSourceScaleway._get_datac             C   s  |  j  d k r. t j d t j  t j |  _  |  j  t j k rG |  j  S|  j d k re t j   |  _ d d d d |  j i } d d i g } |  j d r | d d	 d
 d |  j d d
 d d |  j d d d d |  j d d i g 7} | | d <d d d | g i |  _  |  j  S)z`
        Configure networking according to data received from the
        metadata API.
        Nz5Found None as cached _network_config. Resetting to %stypeZphysicalnamez%sZdhcp4Zipv6ZstaticZaddressZgatewayZnetmasksubnetsversionr    config)	rR   rA   rC   r   rQ   rP   r	   rZ   rV   )r   Znetcfgr`   r   r   r   network_config   s$    	
	
z!DataSourceScaleway.network_configc             C   s   d  S)Nr   )r   r   r   r   launch_index   s    zDataSourceScaleway.launch_indexc             C   s   |  j  d S)Nid)rV   )r   r   r   r   get_instance_id  s    z"DataSourceScaleway.get_instance_idc             C   s   d d   |  j  d D } d } t |  } xR |  j  j d g   D]; } | j |  sZ qB | j | d  |  j d d   qB W| S)Nc             S   s   g  |  ] } | d   q S)keyr   ).0rg   r   r   r   
<listcomp>  s   	 z:DataSourceScaleway.get_public_ssh_keys.<locals>.<listcomp>Zssh_public_keyszAUTHORIZED_KEY=Ztagsr3    )rV   lenrM   
startswithappendreplace)r   Zssh_keysZakeypreplentagr   r   r   get_public_ssh_keys  s    'z&DataSourceScaleway.get_public_ssh_keysFc             C   s   |  j  d S)NZhostname)rV   )r   ZfqdnZ
resolve_ipZmetadata_onlyr   r   r   get_hostname  s    zDataSourceScaleway.get_hostnamec             C   s   d  S)Nr   )r   r   r   r   availability_zone  s    z$DataSourceScaleway.availability_zonec             C   s   d  S)Nr   )r   r   r   r   region  s    zDataSourceScaleway.region)r&   r'   r(   Zdsnamer   ZBOOT_NEW_INSTANCEZBOOTZupdate_eventsr   rW   r]   propertyrc   rd   rf   rq   rr   rs   rt   r   r   )r   r   rG      s   rG   c             C   s   t  j |  t  S)N)r   Zlist_from_dependsdatasources)Zdependsr   r   r   get_datasource_list"  s    rw   )(rT   r   r$   rD   r0   Z$requests.packages.urllib3.connectionr   Z%requests.packages.urllib3.poolmanagerr   Z	cloudinitr   r   Zloggingr   r   r   r	   Zcloudinit.net.dhcpr
   r   Zcloudinit.eventr   Z	getLoggerr&   rA   ZDS_BASE_URLrH   rN   rO   r   ZadaptersZHTTPAdapterr   r=   rF   Z
DataSourcerG   ZDEP_FILESYSTEMrv   rw   r   r   r   r   <module>   s8   

')q