509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
\¼me´=  ã               @   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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„ dej'j(ƒZ)dd„ Z*dd„ Z+G dd„ dej,ƒZ-e-ej.ffgZ/dd„ Z0dS )é    N)Úurlparse)ÚConnectionError)ÚHTTPConnection)ÚPoolManager)ÚdmiÚnetÚsourcesÚ
url_helperÚutil)Ú
EventScopeÚ	EventType)ÚNoDHCPLeaseError)ÚEphemeralDHCPv4ÚEphemeralIPv6Network)ÚDataSourceHostname)ÚProcessExecutionErrorzhttp://169.254.42.42zhttp://[fd00:42::42]é   é   é
   c                   s*   e Zd ZdZ‡ fdd„Zddd„Z‡  ZS )ÚSourceAddressAdapterzF
    Adapter for requests to choose the local address to bind to.
    c                s   || _ tt| ƒjf |Ž d S )N)Úsource_addressÚsuperr   Ú__init__)Úselfr   Úkwargs)Ú	__class__© ú(/usr/lib/python3.6/DataSourceScaleway.pyr   +   s    zSourceAddressAdapter.__init__Fc             C   s0   t jtjtjdfg }t|||| 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_poolmanager/   s    z%SourceAddressAdapter.init_poolmanager)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r#   Ú__classcell__r   r   )r   r   r   &   s   r   c             C   s`   y&t j| d|d|dd„ d�}tj|jƒS  t jk
rZ } z|jdkrHdS ‚ W Y dd}~X nX d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.
    Nr   c             S   s   |j dkot|jtjjƒ S )Ni”  )ÚcodeÚ
isinstanceÚcauseÚrequestsÚ
exceptionsr   )Ú_Úexcr   r   r   Ú<lambda>W   s   
z%query_data_api_once.<locals>.<lambda>)ÚdataÚtimeoutÚretriesZsessionZexception_cbi”  )r	   Úreadurlr
   Údecode_binaryÚcontentsÚUrlErrorr)   )Úapi_addressr2   Úrequests_sessionÚrespr/   r   r   r   Úquery_data_api_once<   s    
r;   c             C   s"  �xt dt|dƒƒD �] }y¶tjd| |ƒ tjƒ }d}yRt|ƒj}|}|d dkr^|dd… }tj	|dtj
d�d d }	|	tjkr†d	}W n tk
rœ   Y nX |jd
t||fd�ƒ t|||d�}
tjd| ƒ |
S  tjk
�r } z$tjd| |ƒ tjdƒ |}wW Y dd}~X qX q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   r   z*Trying to get %s data (bind on port %d)...z0.0.0.0r   ú[N)Úprotoz0::zhttp://)r   )r2   r9   z%s-data downloadedz%Error while trying to get %s data: %sé   éÿÿÿÿ)ÚrangeÚmaxÚLOGÚdebugr,   ZSessionr   Únetlocr"   ÚgetaddrinfoÚIPPROTO_TCPÚAF_INET6Ú
ValueErrorZmountr   r;   r	   r7   ÚwarningÚtimeZsleep)Zapi_typer8   r3   r2   Zportr9   Z	localhostZurl_addressÚaddressÚ
addr_protor1   r/   Úlast_excr   r   r   Úquery_data_apid   s>    




rN   c                   s¬   e Zd ZdZejejejej	hiZ
‡ fdd„Zdd„ Zdd„ Ze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„Zedd„ ƒZedd„ ƒZ‡  ZS )ÚDataSourceScalewayÚScalewayc                s¾   t t| ƒj|||ƒ tjtj|ddgi ƒgƒ| _t| jjdt	ƒƒ| _
t| jjdtƒƒ| _t| jjdtƒƒ| _d | _tj| _t| _d | _d | _d | _d| _d| jjƒ krº|  j| jd 7  _d S )NZ
datasourcerP   r3   r2   Úmax_waitTÚmetadata_urls)r   rO   r   r
   ZmergemanydictZget_cfg_by_pathZds_cfgÚintÚgetÚDEF_MD_RETRIESr3   ÚDEF_MD_TIMEOUTr2   ÚDEF_MD_MAX_WAITrQ   Ú_fallback_interfacer   ÚUNSETÚ_network_configÚDS_BASE_URLSrR   Úuserdata_urlÚvendordata_urlÚephemeral_fixed_addressÚhas_ipv4Úkeys)r   Zsys_cfgÚdistroÚpaths)r   r   r   r   ¢   s    zDataSourceScaleway.__init__c             C   s|   t j ƒ }tj|| j| jdd�\}}|rZtjd|ƒ |› d�| _|› d�| _|› d�| _	dS tjd|t
t j ƒ | ƒƒ t‚dS )	zO
        Define metadata_url based upon api-metadata URL availability.
        F)ÚurlsrQ   r2   Z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)rJ   r	   Zwait_for_urlrQ   r2   rB   rC   Úmetadata_urlr\   r]   rS   r   )r   rc   Z
start_timeZ	avail_urlr.   r   r   r   Ú_set_metadata_url¸   s"    z$DataSourceScaleway._set_metadata_urlc             C   sZ   t j| j| j| jd�}tjtj|j	ƒƒ| _
td| j| j| jƒ| _td| j| j| jƒ| _d S )N)r2   r3   z	user-datazvendor-data)r	   r4   rd   r2   r3   ÚjsonÚloadsr
   r5   r6   ÚmetadatarN   r\   Zuserdata_rawr]   Zvendordata_raw)r   r:   r   r   r   Ú_crawl_metadataÒ   s    z"DataSourceScaleway._crawl_metadatac              C   s>   t jdƒ} | dkrdS tjjdƒr&dS tjƒ }d|kr:dS d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-manufacturerrP   Tz/var/run/scalewayZscalewayN)r   Zread_dmi_dataÚosÚpathÚexistsr
   Zget_cmdline)Zvendor_nameZcmdliner   r   r   Ú	ds_detectß   s    

zDataSourceScaleway.ds_detectc             C   s¨   |dkrt jd|ƒ g S g }x†|D ]~}t|ƒj}|d dkrH|dd	… }tj|d tjd�d d }|tjkr‚|dkr‚||g7 }q"q"|tjkr"|dkr"||g7 }q"q"W |S )
NÚipv4Úipv6zInvalid IP version : %sr   r<   r   )r=   )rn   ro   r?   )	rB   rC   r   rD   r"   rE   rF   ZAF_INETrG   )r   r=   rc   Zfiltered_urlsZurlrK   rL   r   r   r   Ú_set_urls_on_ip_versionô   s$    




z*DataSourceScaleway._set_urls_on_ip_versionc          !   C   s4  | j d krtjƒ | _ | jrºy`t| j| j ƒ�H}tjtj	d| j
| jfd� tjtj	d| jd� |d | _d| jd< W d Q R X W n> tttfk
r¸ } ztjtt|ƒƒ d| _W Y d d }~X nX | j�s0yVt| j| j ƒ�> tjtj	d	| j
| jfd� tjtj	d| jd� d
| jd< W d Q R X W n tk
�r.   dS X dS )Nz3Set api-metadata URL depending on IPv4 availability)ÚlogfuncÚmsgÚfuncÚargszCrawl of metadata service)rq   rr   rs   zfixed-addressrn   Z
net_in_useFz3Set api-metadata URL depending on IPv6 availabilityro   T)rX   r   Úfind_fallback_nicr_   r   ra   r
   Zlog_timerB   rC   re   rR   ri   r^   rh   r   r   r   ZlogexcÚstrr   )r   rn   Úer   r   r   Ú	_get_data  sV    





zDataSourceScaleway._get_datac          	   C   sÞ  | j dkr tjdtjƒ tj| _ | j tjkr2| j S | jdkrFtjƒ | _| jd dk�rFi }i }xÎ| jd D ]À}|d | j	kr–d|d< dd	d
œg|d< qjd|j
ƒ krÈ|d  |d › d|d › �f7  < n|d › d|d › �f|d< |d dkrj|d ddœ}d|j
ƒ k�r |d  |g7  < qj|g|d< qjW ||| j< d|dœ| _ n„dd| j dœ}ddig}| jd �r´|dd| jd d  d| jd d  ddd| jd d  dœgdœg7 }||d < d!|gd"œ| _ tjd#| j ƒ | j S )$z`
        Configure networking according to data received from the
        metadata API.
        Nz5Found None as cached _network_config. Resetting to %sZ
private_ipZ
public_ipsrK   TZdhcp4z169.254.42.42/32z
62.210.0.1)ÚtoÚviaÚroutesZ	addressesú/ÚnetmaskZfamilyZinet6Úgatewayz::/0)rz   ry   r   )ÚversionZ	ethernetsZphysicalz%s)ÚtypeÚnamer€   ro   Zstaticz::Ú0)ZnetworkÚprefixr~   )r€   rK   r}   r{   Úsubnetsr   )r   Úconfigznetwork_config : %s)rZ   rB   rI   r   rY   rX   r   ru   rh   r^   r`   rC   )r   ZnetcfgZip_cfgZipZrouter„   r   r   r   Únetwork_configM  sV    




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)rh   )r   r   r   r   Úget_instance_idž  s    z"DataSourceScaleway.get_instance_idc             C   sb   dd„ | j d D ƒ}d}t|ƒ}x<| j jdg ƒD ]*}|j|ƒs@q0|j||d … jddƒƒ q0W |S )Nc             S   s   g | ]}|d  ‘qS )Úkeyr   )Ú.0rŠ   r   r   r   ú
<listcomp>¢  s    z:DataSourceScaleway.get_public_ssh_keys.<locals>.<listcomp>Zssh_public_keyszAUTHORIZED_KEY=Ztagsr.   ú )rh   ÚlenrT   Ú
startswithÚappendÚreplace)r   Zssh_keysZakeypreZplenÚtagr   r   r   Úget_public_ssh_keys¡  s    
z&DataSourceScaleway.get_public_ssh_keysFc             C   s   t | jd dƒS )NZhostnameF)r   rh   )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)FFF)r$   r%   r&   Zdsnamer   ZNETWORKr   ZBOOT_NEW_INSTANCEZBOOTZBOOT_LEGACYZdefault_update_eventsr   re   ri   Ústaticmethodrm   rp   rx   Úpropertyr†   r‡   r‰   r“   r”   r•   r–   r(   r   r   )r   r   rO   ˜   s$   
AM
rO   c             C   s   t j| tƒS )N)r   Zlist_from_dependsÚdatasources)Zdependsr   r   r   Úget_datasource_list¾  s    rš   )1rf   Zloggingrj   r"   rJ   Zurllib.parser   r,   Zrequests.exceptionsr   Zurllib3.connectionr   Zurllib3.poolmanagerr   Z	cloudinitr   r   r   r	   r
   Zcloudinit.eventr   r   Zcloudinit.net.dhcpr   Zcloudinit.net.ephemeralr   r   Zcloudinit.sourcesr   Zcloudinit.subpr   Z	getLoggerr$   rB   r[   rU   rW   rV   ZadaptersZHTTPAdapterr   r;   rN   Z
DataSourcerO   ZDEP_FILESYSTEMr™   rš   r   r   r   r   Ú<module>   s8   
(4  $