509318396
Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­Â�Â­
<!DOCTYPE html>
<html>
3
\¼me7D  ã               @   s:  d Z 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mZ ddl	m
Z
 ddlmZmZmZmZmZmZ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! ej"e#ƒZ$dZ%dZ&dZ'dddddddœZ(e)dœdd„Z*d9eee)  ee)ef dœdd„Z+G dd„ deƒZ,G dd„ deƒZ-G dd„ deƒZ.e)e/dœdd „Z0G d!d"„ d"ej1ƒZ2e3dœd#d$„Z4d:ej5e)e3d&œd'd(„Z6d;ej5e)e3ej7d)œd*d+„Z8G d,d-„ d-eƒZ9G d.d/„ d/ƒZ:e&e9j;fe)e9e/d0œd1d2„Z<e2ej=ffgZ>d3d4„ Z?e#d5k�r6ddl@Z@d6ZAe@jBeAd7�ZCeCjDƒ  eEejFe<e9j;d8�ƒƒ dS )<a•  Datasource for LXD, reads /dev/lxd/sock representation of instance data.

Notes:
 * This datasource replaces previous NoCloud datasource for LXD.
 * Older LXD images may not have updates for cloud-init so NoCloud may
   still be detected on those images.
 * Detect LXD datasource when /dev/lxd/sock is an active socket file.
 * Info on dev-lxd API: https://documentation.ubuntu.com/lxd/en/latest/dev-lxd/
é    N)ÚFlagÚauto)ÚJSONDecodeError)ÚAnyÚDictÚListÚOptionalÚTupleÚUnionÚcast)ÚHTTPAdapter)ÚHTTPConnection)ÚHTTPConnectionPool)Úatomic_helperÚsourcesÚsubpÚ
url_helperÚutil)Úfind_fallback_nicz/dev/lxd/sockz1.0z
http://lxdz	user-dataznetwork-configzvendor-data)zcloud-init.user-datazcloud-init.network-configzcloud-init.vendor-datazuser.user-datazuser.network-configzuser.vendor-data)Úreturnc              C   sŽ   d} t jdƒrŠyt j dgƒ\}}W n. t jk
rP } ztjd|ƒ | S d }~X nX |jƒ dkrŠtjƒ d d }|dkrzd	S |d
kr†dS dS | S )NZeth0zsystemd-detect-virtzHUnable to run systemd-detect-virt: %s. Rendering default network config.ÚkvmÚqemuÚunameé   Zppc64leZenp0s5Zs390xZenc9Zenp5s0)r   r   )r   ZwhichZProcessExecutionErrorÚLOGÚwarningÚstripr   Zsystem_info)Zdefault_nameZ	virt_typeÚ_ÚerrZarch© r   ú#/usr/lib/python3.6/DataSourceLXD.pyÚ_get_fallback_interface_name/   s&    
 r!   )Únicsr   c             C   sF   t ƒ }|rtjd|ƒ ntƒ }tjd|ƒ dd|dddœgdœgd	œS )
zCReturn network config V1 dict representing instance network config.zCLXD datasource generating network from discovered active device: %szVLXD datasource generating network from systemd-detect-virt platform default device: %sé   ZphysicalZdhcpr   )ÚtypeZcontrol)r$   ÚnameZsubnets)ÚversionÚconfig)r   r   Údebugr!   )r"   Zprimary_nicr   r   r    Úgenerate_network_configI   s    r)   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )ÚSocketHTTPConnectionc                s   t ƒ jdƒ || _d S )NÚ	localhost)ÚsuperÚ__init__Úsocket_path)Úselfr.   )Ú	__class__r   r    r-   p   s    zSocketHTTPConnection.__init__c             C   s$   t j t jt jƒ| _| jj| jƒ d S )N)ÚsocketZAF_UNIXZSOCK_STREAMZsockÚconnectr.   )r/   r   r   r    r2   t   s    zSocketHTTPConnection.connect)Ú__name__Ú
__module__Ú__qualname__r-   r2   Ú__classcell__r   r   )r0   r    r*   o   s   r*   c                   s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )ÚSocketConnectionPoolc                s   || _ tƒ jdƒ d S )Nr+   )r.   r,   r-   )r/   r.   )r0   r   r    r-   z   s    zSocketConnectionPool.__init__c             C   s
   t | jƒS )N)r*   r.   )r/   r   r   r    Ú	_new_conn~   s    zSocketConnectionPool._new_conn)r3   r4   r5   r-   r8   r6   r   r   )r0   r    r7   y   s   r7   c               @   s   e Zd Zddd„ZdS )ÚLXDSocketAdapterNc             C   s   t tƒS )N)r7   ÚLXD_SOCKET_PATH)r/   ÚurlZproxiesr   r   r    Úget_connectionƒ   s    zLXDSocketAdapter.get_connection)N)r3   r4   r5   r<   r   r   r   r    r9   ‚   s   r9   )Úmetadata_typer   c             C   s‚   t |tƒr|S |dkri S ytj|ƒ}W n8 tk
r` } ztjdj| |d�ƒ|‚W Y dd}~X nX |dkr~tjdj| |d�ƒ‚|S )a6  Convert raw instance data from str, bytes, YAML to dict

    :param metadata_type: string, one of as: meta-data, vendor-data, user-data
        network-config

    :param metadata_value: str, bytes or dict representing or instance-data.

    :raises: InvalidMetaDataError on invalid instance-data content.
    NzAInvalid {md_type}. Expected str, bytes or dict but found: {value})Zmd_typeÚvaluez:Invalid {md_type} format. Expected YAML but found: {value})Ú
isinstanceÚdictr   Ú	load_yamlÚAttributeErrorr   ÚInvalidMetaDataExceptionÚformat)r=   Zmetadata_valueZparsed_metadataÚexcr   r   r    Ú_raw_instance_data_to_dict‡   s     


rF   c                   s¸   e Zd ZU dZejZeee	f ejZ
eee	f 
ejjd Zee	df dZed	d
œ‡ fdd„Zeedœdd„ƒZedœdd„Ze	dœdd„Ze	dœdd„Zeedœdd„ƒZ‡  ZS )ÚDataSourceLXDZLXDúuser.meta-dataúuser.vendor-dataúuser.user-dataúcloud-init.user-dataúcloud-init.vendor-data.TN)Úci_pkl_versionr   c                s   t ƒ j|ƒ d| _d S )NT)r,   Ú	_unpickleÚskip_hotplug_detect)r/   rM   )r0   r   r    rN   ·   s    zDataSourceLXD._unpickle)r   c               C   s   t ƒ S )z@Check platform environment to report if this datasource may run.)Úis_platform_viabler   r   r   r    Ú	ds_detect»   s    zDataSourceLXD.ds_detectc             C   sÀ   t jtjdtd�| _td| jjdƒƒ| _| jjdi ƒ}|jdi ƒ}|rPtd|ƒ}t	| jt
ƒstt jt j| jƒ|gƒ| _d| jkrŠ| jd | _d| jkr¦td| jd ƒ| _d| jkr¼| jd | _d	S )
z=Crawl LXD socket API instance data and return True on successzCrawl of metadata service)ZlogfuncÚmsgÚfuncz	meta-datar'   zuser.meta-dataz	user-dataznetwork-configzvendor-dataT)r   Zlog_timer   r(   Úread_metadataÚ_crawled_metadatarF   ÚgetÚmetadatar?   r@   ZmergemanydictrA   Zuserdata_rawÚ_network_configZvendordata_raw)r/   r'   Zuser_metadatar   r   r    Ú	_get_dataÀ   s,    



zDataSourceLXD._get_datac             C   s   dj ttd�S )z.Return subplatform details for this datasourcez"LXD socket API v. {ver} ({socket}))Zverr1   )rD   ÚLXD_SOCKET_API_VERSIONr:   )r/   r   r   r    Ú_get_subplatformÞ   s    zDataSourceLXD._get_subplatformc             C   sB   t tjd�}|jdi ƒ}t|tƒs,tj|ƒ}|jdƒ| jjdƒkS )z%Return True if instance_id unchanged.)Úmetadata_keysz	meta-datazinstance-id)	rT   ÚMetaDataKeysÚ	META_DATArV   r?   r@   r   rA   rW   )r/   Zsys_cfgÚresponseÚmdr   r   r    Úcheck_instance_idä   s
    

zDataSourceLXD.check_instance_idc             C   s¨   | j tjkr~| jtjkr | jƒ  t| jtƒr~| jjdƒrPtj	dƒ | jd | _ n.| jjdƒr~dd„ | jd j
ƒ D ƒ}t|ƒ| _ | j tjkrœtj	dƒ tƒ | _ tt| j ƒS )zŽNetwork config read from LXD socket config/user.network-config.

        If none is present, then we generate fallback configuration.
        znetwork-configz,LXD datasource using provided network configÚdevicesc             S   s    g | ]\}}|d  dkr|‘qS )r$   Znicr   )Ú.0ÚkÚvr   r   r    ú
<listcomp>ÿ   s   z0DataSourceLXD.network_config.<locals>.<listcomp>z8LXD datasource generating network config using fallback.)rX   r   ÚUNSETrU   rY   r?   r@   rV   r   r(   Úitemsr)   r   )r/   rb   r   r   r    Únetwork_configì   s"    


zDataSourceLXD.network_config)rH   rI   rJ   rK   rL   )r3   r4   r5   Zdsnamer   rg   rX   r
   r   ÚstrrU   Ú
DataSourceZsensitive_metadata_keysr	   rO   ÚintrN   ÚstaticmethodÚboolrQ   rY   r[   ra   Úpropertyr@   ri   r6   r   r   )r0   r    rG   ¤   s$   
    rG   c               C   s"   t jjtƒrtjt jtƒjƒS dS )z=Return True when this platform appears to have an LXD socket.F)ÚosÚpathÚexistsr:   ÚstatÚS_ISSOCKÚlstatÚst_moder   r   r   r    rP     s    rP   T)Úsessionr;   Údo_raisec             C   sr   t | ||ƒ}|js*tjd||j|jƒ i S y|jƒ S  tk
rl } ztj	dj
||jd�ƒ|‚W Y d d }~X nX d S )NzSkipping %s on [HTTP:%d]:%szFUnable to process LXD config at {url}. Expected JSON but found: {resp})r;   Úresp)Ú_do_requestÚokr   r(   Ústatus_codeÚtextZjsonr   r   rC   rD   )rw   r;   rx   Zurl_responserE   r   r   r    Ú_get_json_response  s    r~   )rw   r;   rx   r   c             C   s„   xHt ddd
ƒD ]8}| j|ƒ}d|jkrDtjdƒ tjd|j||ƒ qP qW tjd|j|ƒ |r€|j r€t	j
dj|j||jd	�ƒ‚|S )Né   r   r#   iô  gš™™™™™¹?z,[GET] [HTTP:%d] %s, retrying %d more time(s)z[GET] [HTTP:%d] %sz3Invalid HTTP response [{code}] from {route}: {resp})ÚcodeZroutery   éÿÿÿÿ)ÚrangerV   r|   ÚtimeZsleepr   r   r(   r{   r   rC   rD   r}   )rw   r;   rx   Zretriesr_   r   r   r    rz   ,  s$    


rz   c               @   s0   e Zd Zeƒ Zeƒ Zeƒ Zeƒ ZeeB eB ZdS )r]   N)	r3   r4   r5   r   ZNONEÚCONFIGÚDEVICESr^   ÚALLr   r   r   r    r]   I  s
   r]   c               @   s@   e Zd Zefedœdd„Zejedœdd„Z	e
edœdd	„Zd
S )Ú_MetaDataReader)Úapi_versionc             C   s   || _ tjt| j ƒ| _d S )N)rˆ   r   Úcombine_urlÚLXD_URLÚ_version_url)r/   rˆ   r   r   r    r-   R  s    z_MetaDataReader.__init__)rw   r   c       	      C   sÄ   di i}t j| jdƒ}t||ƒ}xžt|ƒD ]’}t jt|ƒ}t||dd�}|jsdtj	d||j
|jƒ q*|jdƒd
 }|j|d |< |tkr*t| |kr¤|j|t| < q*tjd||jdd	dƒƒ q*W |S )a’  Iterate on LXD API config items. Promoting CONFIG_KEY_ALIASES

        Any CONFIG_KEY_ALIASES which affect cloud-init behavior are promoted
        as top-level configuration keys: user-data, network-data, vendor-data.

        LXD's cloud-init.* config keys override any user.* config keys.
        Log debug messages if any user.* keys are overridden by the related
        cloud-init.* key.
        r'   F)rx   zSkipping %s on [HTTP:%d]:%sú/r#   z,Ignoring LXD config %s in favor of %s value.Úuserz
cloud-initr�   )r   r‰   r‹   r~   ÚsortedrŠ   rz   r{   r   r(   r|   r}   Ú
rpartitionÚCONFIG_KEY_ALIASESr   Úreplace)	r/   rw   r'   Z
config_urlZconfig_routesZconfig_routeZconfig_route_urlZconfig_route_responseZcfg_keyr   r   r    Ú_process_configV  s0    

z_MetaDataReader._process_config)r\   r   c            C   s¦   t jƒ �”}|j| jtƒ ƒ d| ji}tj|krLtj	| jdƒ}t
||ƒj|d< tj|krf|j| j|ƒƒ tj|kr˜tj	| jdƒ}t||dd�}|r˜||d< |S Q R X d S )NZ_metadata_api_versionz	meta-datarb   F)rx   )ÚrequestsÚSessionZmountr‹   r9   rˆ   r]   r^   r   r‰   rz   r}   r„   Úupdater’   r…   r~   )r/   r\   rw   r`   Zmd_router;   rb   r   r   r    Ú__call__�  s    





z_MetaDataReader.__call__N)r3   r4   r5   rZ   rj   r-   r“   r”   r@   r’   r]   r–   r   r   r   r    r‡   Q  s   7r‡   )rˆ   r\   r   c             C   s   t | d�|d�S )a8  Fetch metadata from the /dev/lxd/socket routes.

    Perform a number of HTTP GETs on known routes on the devlxd socket API.
    Minimally all containers must respond to <LXD_SOCKET_API_VERSION>/meta-data
    when the LXD configuration setting `security.devlxd` is true.

    When `security.devlxd` is false, no /dev/lxd/socket file exists. This
    datasource will return False from `is_platform_viable` in that case.

    Perform a GET of <LXD_SOCKET_API_VERSION>/config` and walk all `user.*`
    configuration keys, storing all keys and values under a dict key
        LXD_SOCKET_API_VERSION: config {...}.

    In the presence of the following optional user config keys,
    create top level aliases:
      - user.user-data -> user-data
      - user.vendor-data -> vendor-data
      - user.network-config -> network-config

    :param api_version:
        LXD API version to operated with.
    :param metadata_keys:
        Instance of `MetaDataKeys` indicating what keys to fetch.
    :return:
        A dict with the following optional keys: meta-data, user-data,
        vendor-data, network-config, network_mode, devices.

        Below <LXD_SOCKET_API_VERSION> is a dict representation of all raw
        configuration keys and values provided to the container surfaced by
        the socket under the /1.0/config/ route.
    )rˆ   )r\   )r‡   )rˆ   r\   r   r   r    rT   ¡  s    #rT   c             C   s   t j| tƒS )N)r   Zlist_from_dependsÚdatasources)Zdependsr   r   r    Úget_datasource_listÐ  s    r˜   Ú__main__z*Query LXD metadata and emit a JSON object.)Údescription)r\   )N)T)T)GÚ__doc__Zloggingrp   r1   rs   rƒ   Úenumr   r   Zjson.decoderr   Ztypingr   r   r   r   r	   r
   r   r“   Zrequests.adaptersr   Zurllib3.connectionr   Zurllib3.connectionpoolr   Z	cloudinitr   r   r   r   r   Zcloudinit.netr   Z	getLoggerr3   r   r:   rZ   rŠ   r�   rj   r!   r)   r*   r7   r9   r@   rF   rk   rG   rn   rP   r”   r~   ZResponserz   r]   r‡   r†   rT   ZDEP_FILESYSTEMr—   r˜   Úargparserš   ÚArgumentParserÚparserÚ
parse_argsÚprintZ
json_dumpsr   r   r   r    Ú<module>	   sd   $
$
	j
Q
'
