a '¡DgÑDã@s:dZddlZddlZddlZddlZddlZddlmZmZddl m Z ddl m Z m Z mZmZmZmZmZddlZddlmZddlmZddlmZdd lmZmZmZmZmZdd l m!Z!e "e#¡Z$d Z%d Z&d Z'dddddddœZ(e)dœdd„Z*d9eee)e e)e fdœdd„Z+Gdd„deƒZ,Gdd„deƒZ-Gdd„deƒZ.e)e/dœdd „Z0Gd!d"„d"ej1ƒZ2e3dœd#d$„Z4d:ej5e)e3d&œd'd(„Z6d;ej5e)e3ej7d)œd*d+„Z8Gd,d-„d-eƒZ9Gd.d/„d/ƒZ:e&e9j;fe)e9e/d0œd1d2„Zd3d4„Z?e#d5k�r6ddl@Z@d6ZAe@jBeAd7�ZCeC D¡eEe FeuszSocketHTTPConnection.connect)Ú__name__Ú __module__Ú __qualname__r5r>Ú __classcell__r&r&r:r'r2os r2cs$eZdZ‡fdd„Zdd„Z‡ZS)ÚSocketConnectionPoolcs||_tƒ d¡dSr3)r6r4r5r8r:r&r'r5{szSocketConnectionPool.__init__cCs t|jƒSr<)r2r6r?r&r&r'Ú _new_connszSocketConnectionPool._new_conn)r@rArBr5rErCr&r&r:r'rDzs rDc@s eZdZddd„Zddd„ZdS)ÚLXDSocketAdapterNcCsttƒSr<)rDÚLXD_SOCKET_PATH)r9ÚurlÚproxiesr&r&r'Úget_connection„szLXDSocketAdapter.get_connectioncCs| |j|¡Sr<)rJrH)r9ZrequestZverifyrIZcertr&r&r'Úget_connection_with_tls_context‰sz0LXDSocketAdapter.get_connection_with_tls_context)N)NN)r@rArBrJrKr&r&r&r'rFƒs ÿrF)Ú metadata_typerc Cs„t|tƒr|S|duriSzt |¡}Wn:tyb}z"t dj||d�¡|‚WYd}~n d}~00|dur€t dj||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_typeÚvaluez:Invalid {md_type} format. Expected YAML but found: {value})Ú isinstanceÚdictrÚ load_yamlÚAttributeErrorrÚInvalidMetaDataExceptionÚformat)rLZmetadata_valueZparsed_metadataÚexcr&r&r'Ú_raw_instance_data_to_dict�s* ÿÿýÿÿrUcsÈeZdZUdZejZeee fe d<ejZ e eee fe d<ej jdZee dfe d<dZedd œ‡fd d „ Zeed œd d„ƒZed œdd„Ze d œdd„Ze d œdd„Zeed œdd„ƒZ‡ZS)Ú DataSourceLXDZLXDÚ_network_configÚ_crawled_metadata)úuser.meta-datarrrr.Úsensitive_metadata_keysTN)Úci_pkl_versionrcstƒ |¡d|_dS)NT)r4Ú _unpickleÚskip_hotplug_detect)r9r[r:r&r'r\Às zDataSourceLXD._unpicklercCstƒS)z@Check platform environment to report if this datasource may run.)Úis_platform_viabler&r&r&r'Ú ds_detectÄszDataSourceLXD.ds_detectcCs˜tƒ|_td|j d¡ƒ|_|j di¡}| di¡}|rL|j td|ƒ¡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_metadatarXrUÚgetÚmetadataÚupdateZ userdata_rawrWZvendordata_raw)r9r/Z user_metadatar&r&r'Ú _get_dataÉs& ÿ ÿ    ÿ  zDataSourceLXD._get_datacCsdjttd�S)z.Return subplatform details for this datasourcez"LXD socket API v. {ver} ({socket}))Zverr=)rSÚLXD_SOCKET_API_VERSIONrGr?r&r&r'Ú_get_subplatformßsÿzDataSourceLXD._get_subplatformcCsBttjd�}| di¡}t|tƒs,t |¡}| d¡|j d¡kS)z%Return True if instance_id unchanged.©Ú metadata_keysr`z instance-id) raÚ MetaDataKeysÚ META_DATArbrNrOrrPrc)r9Zsys_cfgÚresponseÚmdr&r&r'Úcheck_instance_idås     zDataSourceLXD.check_instance_idcCs¨|jtjkr~|jtjkr | ¡t|jtƒr~|j d¡rPt  d¡|jd|_n.|j d¡r~dd„|jd  ¡Dƒ}t |ƒ|_|jtjkrœt  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. rz,LXD datasource using provided network configÚdevicescSs g|]\}}|ddkr|‘qS)r+Znicr&)Ú.0ÚkÚvr&r&r'Ú ÿs þz0DataSourceLXD.network_config..z8LXD datasource generating network config using fallback.) rWrÚUNSETrXrerNrOrbr!r0Úitemsr1r )r9ror&r&r'Únetwork_configís(     ÿ  þ  ÿzDataSourceLXD.network_config)r@rArBZdsnamerrtrWr rÚstrÚ__annotations__rXrÚ DataSourcerZr r]Úintr\Ú staticmethodÚboolr_rergrnÚpropertyrOrvrCr&r&r:r'rV¬s ÿÿ rVcCs"tj t¡rt t t¡j¡SdS)z=Return True when this platform appears to have an LXD socket.F)ÚosÚpathÚexistsrGÚstatÚS_ISSOCKÚlstatÚst_moder&r&r&r'r^s r^T)ÚsessionrHÚdo_raisec Cs‚t|||ƒ}|js0t d||j|j d¡¡iSz | ¡WSty|}z*t   dj ||j d¡d�¡|‚WYd}~n d}~00dS)NúSkipping %s on [HTTP:%d]:%súutf-8zFUnable to process LXD config at {url}. Expected JSON but found: {resp})rHÚresp) Ú _do_requestÚokr!r0Ú status_codeÚcontentÚdecodeZjsonrrrRrS)r…rHr†Z url_responserTr&r&r'Ú_get_json_responses&  ü  þÿûr�)r…rHr†rcCs†tdddƒD]:}| |¡}d|jkrBt d¡t d|j||¡q qHq t d|j|¡|r‚|js‚t   dj |j||j   d ¡d �¡‚|S) Néréÿÿÿÿiôgš™™™™™¹?z,[GET] [HTTP:%d] %s, retrying %d more time(s)z[GET] [HTTP:%d] %sz3Invalid HTTP response [{code}] from {route}: {resp}rˆ)ÚcodeZrouter‰)ÚrangerbrŒÚtimeÚsleepr!r"r0r‹rrRrSr�rŽ)r…rHr†Zretriesrlr&r&r'rŠ-s*   ü  ýÿrŠc@s0eZdZeƒZeƒZeƒZeƒZeeBeBZdS)rjN) r@rArBrZNONEÚCONFIGÚDEVICESrkÚALLr&r&r&r'rjJs rjc@s@eZdZefedœdd„Zejedœdd„Z e edœdd „Z d S) Ú_MetaDataReader©Ú api_versioncCs||_t t|j¡|_dSr<)r›rÚ combine_urlÚLXD_URLÚ _version_url)r9r›r&r&r'r5Ssz_MetaDataReader.__init__)r…rc CsÆdii}t |jd¡}t||ƒ}t|ƒD]˜}t t|¡}t||dd�}|j d¡}|j slt   d||j |¡q(|  d¡d} ||d| <| tvr(t| |vr¨||t| <q(t  d| |  d d d ¡¡q(|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©r†rˆr‡ú/r‘z,Ignoring LXD config %s in favor of %s value.Úuserz cloud-initr*)rrœržr�Úsortedr�rŠr�rŽr‹r!r0rŒÚ rpartitionÚCONFIG_KEY_ALIASESr"Úreplace) r9r…r/Z config_urlZ config_routesZ config_routeZconfig_route_urlZconfig_route_responseZ response_textZcfg_keyr&r&r'Ú_process_configWs8    ÿ ü   ýz_MetaDataReader._process_config)rircCsÄt ¡�¨}| |jtƒ¡d|ji}tj|vrRt  |jd¡}t ||ƒj   d¡|d<tj |vrl| | |¡¡tj|vržt  |jd¡}t||dd�}|rž||d<|WdƒS1s¶0YdS)NZ_metadata_api_versionr`rˆroFrŸ)ÚrequestsÚSessionZmountržrFr›rjrkrrœrŠr�rŽr–rdr¦r—r�)r9rir…rmZmd_routerHror&r&r'Ú__call__�s(   ÿÿþ  z_MetaDataReader.__call__N) r@rArBrfrwr5r§r¨rOr¦rjr©r&r&r&r'r™Rs6r™)r›rircCst|d�|d�S)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. ršrh)r™)r›rir&r&r'ra£s#ÿracCs t |t¡Sr<)rZlist_from_dependsÚ datasources)Zdependsr&r&r'Úget_datasource_listÒsr«Ú__main__z*Query LXD metadata and emit a JSON object.)Ú descriptionrh)N)T)T)GÚ__doc__Zloggingr~r=r�r”ÚenumrrZ json.decoderrÚtypingrrrrr r r r§Zrequests.adaptersr Zurllib3.connectionr Zurllib3.connectionpoolrZ cloudinitrrrrrZ cloudinit.netrZ getLoggerr@r!rGrfr�r¤rwr(r1r2rDrFrOrUryrVr|r^r¨r�ZResponserŠrjr™r˜raZDEP_FILESYSTEMrªr«Úargparser­ÚArgumentParserÚparserÚ parse_argsÚprintZ json_dumpsr&r&r&r'Ús„  $     ú ÿ  þ &   cÿÿ ÿþ Rþý * ÿ  ÿ