a 'DgD@s:dZddlZddlZddlZddlZddlZddlmZmZddl m Z ddl m Z m Z mZmZmZmZmZddlZddlmZddlmZddlmZdd lmZmZmZmZmZdd l m!Z!e"e#Z$d Z%d Z&d Z'dddddddZ(e)dddZ*d9eee)e e)e fdddZ+GdddeZ,GdddeZ-GdddeZ.e)e/ddd Z0Gd!d"d"ej1Z2e3dd#d$Z4d:ej5e)e3d&d'd(Z6d;ej5e)e3ej7d)d*d+Z8Gd,d-d-eZ9Gd.d/d/Z:e&e9j;fe)e9e/d0d1d2Zd3d4Z?e#d5kr6ddl@Z@d6ZAe@jBeAd7ZCeCDeEeFeuszSocketHTTPConnection.connect)__name__ __module__ __qualname__r5r> __classcell__r&r&r:r'r2os r2cs$eZdZfddZddZZS)SocketConnectionPoolcs||_tddSr3)r6r4r5r8r:r&r'r5{szSocketConnectionPool.__init__cCs t|jSr<)r2r6r?r&r&r' _new_connszSocketConnectionPool._new_conn)r@rArBr5rErCr&r&r:r'rDzs rDc@s eZdZdddZdddZdS)LXDSocketAdapterNcCsttSr<)rDLXD_SOCKET_PATH)r9urlproxiesr&r&r'get_connectionszLXDSocketAdapter.get_connectioncCs||j|Sr<)rJrH)r9ZrequestZverifyrIZcertr&r&r'get_connection_with_tls_contextsz0LXDSocketAdapter.get_connection_with_tls_context)N)NN)r@rArBrJrKr&r&r&r'rFs rF) metadata_typerc Cst|tr|S|duriSzt|}Wn:tyb}z"tdj||d|WYd}~n d}~00|durtdj||d|S)a6Convert 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})Zmd_typevaluez:Invalid {md_type} format. Expected YAML but found: {value}) isinstancedictr load_yamlAttributeErrorrInvalidMetaDataExceptionformat)rLZmetadata_valueZparsed_metadataexcr&r&r'_raw_instance_data_to_dicts* rUcseZdZUdZejZeee fe d<ejZ e eee fe d<ej jdZee dfe d<dZedd fd d Zeed d dZed ddZe d ddZe d ddZeed ddZZS) DataSourceLXDZLXD_network_config_crawled_metadata)user.meta-datarrrr.sensitive_metadata_keysTN)ci_pkl_versionrcst|d|_dS)NT)r4 _unpickleskip_hotplug_detect)r9r[r:r&r'r\s zDataSourceLXD._unpicklercCstS)z@Check platform environment to report if this datasource may run.)is_platform_viabler&r&r&r' ds_detectszDataSourceLXD.ds_detectcCst|_td|jd|_|jdi}|di}|rL|jtd|d|jvrb|jd|_d|jvr~td|jd|_d|jvr|jd|_dS)z=Crawl LXD socket API instance data and return True on success meta-datar/rYrrrT) read_metadatarXrUgetmetadataupdateZ userdata_rawrWZvendordata_raw)r9r/Z user_metadatar&r&r' _get_datas&        zDataSourceLXD._get_datacCsdjttdS)z.Return subplatform details for this datasourcez"LXD socket API v. {ver} ({socket}))Zverr=)rSLXD_SOCKET_API_VERSIONrGr?r&r&r'_get_subplatformszDataSourceLXD._get_subplatformcCsBttjd}|di}t|ts,t|}|d|jdkS)z%Return True if instance_id unchanged. metadata_keysr`z instance-id) ra MetaDataKeys META_DATArbrNrOrrPrc)r9Zsys_cfgresponsemdr&r&r'check_instance_ids     zDataSourceLXD.check_instance_idcCs|jtjkr~|jtjkr |t|jtr~|jdrPt d|jd|_n.|jdr~dd|jd D}t ||_|jtjkrt dt |_t t|jS)zNetwork config read from LXD socket config/user.network-config. If none is present, then we generate fallback configuration. rz,LXD datasource using provided network configdevicescSs g|]\}}|ddkr|qS)r+Znicr&).0kvr&r&r' s z0DataSourceLXD.network_config..z8LXD datasource generating network config using fallback.) rWrUNSETrXrerNrOrbr!r0itemsr1r )r9ror&r&r'network_configs(         zDataSourceLXD.network_config)r@rArBZdsnamerrtrWr rstr__annotations__rXr DataSourcerZr r]intr\ staticmethodboolr_rergrnpropertyrOrvrCr&r&r:r'rVs  rVcCs"tjtrtttjSdS)z=Return True when this platform appears to have an LXD socket.F)ospathexistsrGstatS_ISSOCKlstatst_moder&r&r&r'r^s r^T)sessionrHdo_raisec Cst|||}|js0td||j|jdiSz |WSty|}z*t dj ||jdd|WYd}~n d}~00dS)NSkipping %s on [HTTP:%d]:%sutf-8zFUnable to process LXD config at {url}. Expected JSON but found: {resp})rHresp) _do_requestokr!r0 status_codecontentdecodeZjsonrrrRrS)rrHrZ url_responserTr&r&r'_get_json_responses&    r)rrHrrcCstdddD]:}||}d|jkrBtdtd|j||q qHq td|j||r|jst dj |j||j d d |S) Nrig?z,[GET] [HTTP:%d] %s, retrying %d more time(s)z[GET] [HTTP:%d] %sz3Invalid HTTP response [{code}] from {route}: {resp}r)codeZrouter)rangerbrtimesleepr!r"r0rrrRrSrr)rrHrZretriesrlr&r&r'r-s*     rc@s0eZdZeZeZeZeZeeBeBZdS)rjN) r@rArBrZNONECONFIGDEVICESrkALLr&r&r&r'rjJs rjc@s@eZdZefedddZejedddZ e eddd Z d S) _MetaDataReader api_versioncCs||_tt|j|_dSr<)rr combine_urlLXD_URL _version_url)r9rr&r&r'r5Ssz_MetaDataReader.__init__)rrc Csdii}t|jd}t||}t|D]}tt|}t||dd}|jd}|j slt d||j |q(| dd} ||d| <| tvr(t| |vr||t| <q(t d| | d d d q(|S) aIterate 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/Frrr/rz,Ignoring LXD config %s in favor of %s value.userz cloud-initr*)rrrrsortedrrrrrr!r0r rpartitionCONFIG_KEY_ALIASESr"replace) r9rr/Z config_urlZ config_routesZ config_routeZconfig_route_urlZconfig_route_responseZ response_textZcfg_keyr&r&r'_process_configWs8        z_MetaDataReader._process_config)rircCst}||jtd|ji}tj|vrRt |jd}t ||j d|d<tj |vrl|||tj|vrt |jd}t||dd}|r||d<|WdS1s0YdS)NZ_metadata_api_versionr`rroFr)requestsSessionZmountrrFrrjrkrrrrrrrdrrr)r9rirrmZmd_routerHror&r&r'__call__s(     z_MetaDataReader.__call__N) r@rArBrfrwr5rrrOrrjrr&r&r&r'rRs6r)rrircCst|d|dS)a8Fetch 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 /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 /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 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. rrh)r)rrir&r&r'ras#racCs t|tSr<)rZlist_from_depends datasources)Zdependsr&r&r'get_datasource_listsr__main__z*Query LXD metadata and emit a JSON object.) descriptionrh)N)T)T)G__doc__Zloggingr~r=rrenumrrZ json.decoderrtypingrrrrr r r rZrequests.adaptersr Zurllib3.connectionr Zurllib3.connectionpoolrZ cloudinitrrrrrZ cloudinit.netrZ getLoggerr@r!rGrfrrrwr(r1r2rDrFrOrUryrVr|r^rrZResponserrjrrraZDEP_FILESYSTEMrrargparserArgumentParserparser parse_argsprintZ json_dumpsr&r&r&r's  $        &   c  R *