
    x[hD              	       `   S r SSKrSSKrSSKrSSKrSSKrSSKJrJr  SSK	J
r
  SSKJrJrJrJrJrJrJr  SSKrSSKJr  SSKJr  SSKJr  SS	KJrJrJrJrJr  SS
K J!r!  \RD                  " \#5      r$Sr%Sr&Sr'SSSSSSS.r(S\)4S jr* S1S\\\)      S\\)\4   4S jjr+ " S S\5      r, " S S\5      r- " S S\5      r.S\)S\/4S jr0 " S S\Rb                  5      r2 S2S \Rf                  S!\)S"\44S# jjr5 S2S \Rf                  S!\)S"\4S\Rl                  4S$ jjr7 " S% S&\5      r8 " S' S(5      r9\&\8Rt                  4S)\)S*\8S\/4S+ jjr;\2\Rx                  44/r=S, r>\#S-:X  aM  SSK?r?S.r@\?R                  " \@S/9rB\BR                  5         \D" \R                  " \;" \8Rt                  S095      5        gg)3a  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://lxd	user-datanetwork-configvendor-data)cloud-init.user-datazcloud-init.network-configcloud-init.vendor-datauser.user-datazuser.network-configuser.vendor-datareturnc                  b   Sn [         R                  " S5      (       aX   [         R                   " S/5      u  pUR                  5       S;   a*  [        R                  " 5       S   S   nUS:X  a  gUS	:X  a  g
gU $ ! [         R                   a"  n[        R	                  SU5        U s S nA$ S nAff = f)Neth0zsystemd-detect-virtzHUnable to run systemd-detect-virt: %s. Rendering default network config.)kvmqemuuname   ppc64leenp0s5s390xenc9enp5s0)r   whichProcessExecutionErrorLOGwarningstripr   system_info)default_name	virt_type_errarchs        A/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceLXD.py_get_fallback_interface_namer5   /   s    Lzz'((	 99&;%<=LI ?? !
 
 ##%g.q1Dy % )) 	 KK5
  	 s   A8 8B.B)#B.)B.nicsc                     [        5       nU(       a  [        R                  SU5        O [        5       n[        R                  SU5        SSUSSS./S./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   physicaldhcpr   )typecontrol)r;   namesubnets)versionconfig)r   r+   debugr5   )r6   primary_nics     r4   generate_network_configrC   I   sm     $%K			
 34		+	
  ##%+?@
	 	    c                   .   ^  \ rS rSrU 4S jrS rSrU =r$ )SocketHTTPConnectiono   c                 >   > [         TU ]  S5        Xl        S U l        g N	localhost)super__init__socket_pathsockselfrM   	__class__s     r4   rL   SocketHTTPConnection.__init__p   s    %&	rD   c                     [         R                   " [         R                  [         R                  5      U l        U R                  R	                  U R
                  5        g N)socketAF_UNIXSOCK_STREAMrN   connectrM   rP   s    r4   rX   SocketHTTPConnection.connectu   s6    MM&..&2D2DE			$**+rD   )rN   rM   )__name__
__module____qualname____firstlineno__rL   rX   __static_attributes____classcell__rQ   s   @r4   rF   rF   o   s    
, ,rD   rF   c                   .   ^  \ rS rSrU 4S jrS rSrU =r$ )SocketConnectionPoolz   c                 0   > Xl         [        TU ]	  S5        g rI   )rM   rK   rL   rO   s     r4   rL   SocketConnectionPool.__init__{   s    &%rD   c                 ,    [        U R                  5      $ rT   )rF   rM   rY   s    r4   	_new_connSocketConnectionPool._new_conn   s    #D$4$455rD   )rM   )r[   r\   r]   r^   rL   rh   r_   r`   ra   s   @r4   rc   rc   z   s    &6 6rD   rc   c                   *    \ rS rSrSS jr SS jrSrg)LXDSocketAdapter   Nc                      [        [        5      $ rT   )rc   LXD_SOCKET_PATH)rP   urlproxiess      r4   get_connectionLXDSocketAdapter.get_connection   s    #O44rD   c                 :    U R                  UR                  U5      $ rT   )rq   ro   )rP   requestverifyrp   certs        r4   get_connection_with_tls_context0LXDSocketAdapter.get_connection_with_tls_context   s     ""7;;88rD    rT   )NN)r[   r\   r]   r^   rq   rw   r_   ry   rD   r4   rk   rk      s    5 379rD   rk   metadata_typec                 $   [        U[        5      (       a  U$ Uc  0 $  [        R                  " U5      nUc#  [
        R                  " SR                  XS95      eU$ ! [         a)  n[
        R                  " SR                  XS95      UeSnAff = f)a"  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})md_typevaluez:Invalid {md_type} format. Expected YAML but found: {value})
isinstancedictr   	load_yamlAttributeErrorr   InvalidMetaDataExceptionformat)rz   metadata_valueparsed_metadataexcs       r4   _raw_instance_data_to_dictr      s     .$''	..8 ..vmvJ
 	
   ..vmvJ
 	s   A 
B&$B

Bc                   <  ^  \ rS rSr% Sr\R                  r\\	\
4   \S'   \R                  r\\\	\
4      \S'   \R                  R                  S-   r\\
S4   \S'   SrS	\S
S4U 4S jjr\S
\4S j5       rS
\4S jrS
\
4S jrS
\
4S jr\S
\4S j5       rSrU =r$ )DataSourceLXD   LXD_network_config_crawled_metadata)user.meta-datar   r   r   r   .sensitive_metadata_keysTci_pkl_versionr   Nc                 2   > [         TU ]  U5        SU l        g )NT)rK   	_unpickleskip_hotplug_detect)rP   r   rQ   s     r4   r   DataSourceLXD._unpickle   s    .)#' rD   c                  :   [         R                  R                  [        5      (       d  [        R                  S[        5        g[        R                  " [         R                  " [        5      R                  5      (       d  [        R                  S[        5        gg)z@Check platform environment to report if this datasource may run.z%s does not exist.Fz%s is not a socketT)
ospathexistsrn   r+   r,   statS_ISSOCKlstatst_modery   rD   r4   	ds_detectDataSourceLXD.ds_detect   s\     ww~~o..KK,o>rxx8@@AAKK,o>rD   c                    [        5       U l        [        SU R                  R                  S5      5      U l        U R                  R                  S0 5      nUR                  S0 5      nU(       a%  U R                  R                  [        SU5      5        SU R                  ;   a  U R                  S   U l        SU R                  ;   a  [        SU R                  S   5      U l        SU R                  ;   a  U R                  S   U l        g)z=Crawl LXD socket API instance data and return True on success	meta-datar@   r   r   r   r   T)	read_metadatar   r   getmetadataupdateuserdata_rawr   vendordata_raw)rP   r@   user_metadatas      r4   	_get_dataDataSourceLXD._get_data   s    !.2//33K@
 ''++Hb9

#3R8MM  *+;]K $000 $ 6 6{ CDt555#= $"8"89I"J$D  D222"&"8"8"GDrD   c                 2    SR                  [        [        S9$ )z.Return subplatform details for this datasourcez"LXD socket API v. {ver} ({socket}))verrU   )r   LXD_SOCKET_API_VERSIONrn   rY   s    r4   _get_subplatformDataSourceLXD._get_subplatform   s    3::& ; 
 	
rD   c                    [        [        R                  S9nUR                  S0 5      n[	        U[
        5      (       d  [        R                  " U5      nUR                  S5      U R                  R                  S5      :H  $ )z%Return True if instance_id unchanged.metadata_keysr   zinstance-id)	r   MetaDataKeys	META_DATAr   r~   r   r   r   r   )rP   sys_cfgresponsemds       r4   check_instance_idDataSourceLXD.check_instance_id   s`     |/E/EF\\+r*"d###Bvvm$(9(9-(HHHrD   c                 
   U R                   [        R                  :X  Ga  U R                  [        R                  :X  a  U R	                  5         [        U R                  [        5      (       a  U R                  R                  S5      (       a*  [        R                  S5        U R                  S   U l         OlU R                  R                  S5      (       aL  U R                  S   R                  5        VVs/ s H  u  pUS   S:X  d  M  UPM     nnn[        U5      U l         U R                   [        R                  :X  a$  [        R                  S5        [        5       U l         [        [        U R                   5      $ s  snnf )z~Network config read from LXD socket config/user.network-config.

If none is present, then we generate fallback configuration.
r   z,LXD datasource using provided network configdevicesr;   nicz8LXD datasource generating network config using fallback.)r   r   UNSETr   r   r~   r   r   r+   rA   itemsrC   r   )rP   kvr   s       r4   network_configDataSourceLXD.network_config   s3    7==0%%6 $00$77))--.>??IILM+/+A+A(,D( ++//	::
 %)$:$:9$E$K$K$M*$MDAV9- $M  *
 ,C7+KD(7==0IIJ $;#<D D$..//*s   7E?
E?)r   r   r   r   r   r   )r[   r\   r]   r^   dsnamer   r   r   r   r   str__annotations__r   r	   
DataSourcer   r
   r   intr   staticmethodboolr   r   r   r   propertyr   r   r_   r`   ra   s   @r4   r   r      s    F(/OU49%54;MMxdCi 01A 	22
	
 U38_ 	 ( ( ( t  4 ,
# 
IC I 0 0 0rD   r   sessionro   do_raisec           	      v   [        XU5      nUR                  (       d=  [        R                  SUUR                  UR
                  R                  S5      5        0 $  UR                  5       $ ! [         aB  n[        R                  " SR                  XR
                  R                  S5      S95      UeS nAff = f)NSkipping %s on [HTTP:%d]:%sutf-8zFUnable to process LXD config at {url}. Expected JSON but found: {resp})ro   resp)_do_requestokr+   rA   status_codecontentdecodejsonr   r   r   r   )r   ro   r   url_responser   s        r4   _get_json_responser     s     wX6L??		)$$  ''0		
 	  "" ..//5v2299'B 06 0

 	s   A, ,
B86=B33B8c           	         [        SSS5       H^  nU R                  U5      nSUR                  :X  a:  [        R                  " S5        [
        R                  SUR                  UU5        M^    O   [
        R                  SWR                  U5        U(       aY  UR                  (       dH  [        R                  " SR                  UR                  UUR                  R                  S	5      S
95      eU$ )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   )coderouter   )ranger   r   timesleepr+   r,   rA   r   r   r   r   r   r   )r   ro   r   retriesr   s        r4   r   r   ,  s     Q#;;s#(&&& JJsOKK>$$	  $ II"H$8$8#>..AHH))%%,,W5 I 
 	
 OrD   c                   \    \ rS rSr\" 5       r\" 5       r\" 5       r\" 5       r\\-  \-  r	Sr
g)r   iI  ry   N)r[   r\   r]   r^   r   NONECONFIGDEVICESr   ALLr_   ry   rD   r4   r   r   I  s-    6DVFfGI
7
Y
&CrD   r   c                   `    \ rS rSr\4S\4S jjrS\R                  S\	4S jr
S\S\	4S jrS	rg
)_MetaDataReaderiQ  api_versionc                 d    Xl         [        R                  " [        U R                   5      U l        g rT   )r   r   combine_urlLXD_URL_version_url)rP   r   s     r4   rL   _MetaDataReader.__init__R  s#    &&227D<L<LMrD   r   r   c           
      F   S0 0n[         R                  " U R                  S5      n[        X5      n[	        U5       H  n[         R                  " [
        U5      n[        XSS9nUR                  R                  S5      nUR                  (       d$  [        R                  SUUR                  U5        Mx  UR                  S5      S   n	XS   U	'   U	[        ;   d  M  [        U	   U;  a  X[        U	   '   M  [        R                  SU	U	R!                  S	S
S5      5        M     U$ )ab  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-initr8   )r   r   r   r   sortedr   r   r   r   r   r+   rA   r   
rpartitionCONFIG_KEY_ALIASESr,   replace)
rP   r   r@   
config_urlconfig_routesconfig_routeconfig_route_urlconfig_route_responseresponse_textcfg_keys
             r4   _process_config_MetaDataReader._process_configV  s    !"~++D,=,=xH
 +7?
 #=1L)55g|L$/E%! 299@@IM(++		1$)55!	 "--c226G )68W%,, &g.f<:G-g67KKFa@9 2B rD   r   c                ~   [         R                  " 5        nUR                  U R                  [	        5       5        SU R
                  0n[        R                  U;   aH  [        R                  " U R                  S5      n[        X$5      R                  R                  S5      US'   [        R                  U;   a   UR                  U R                  U5      5        [        R                   U;   a6  [        R                  " U R                  S5      n[#        X%SS9nU(       a  XcS'   UsS S S 5        $ ! , (       d  f       g = f)N_metadata_api_versionr   r   r   Fr   )requestsSessionmountr   rk   r   r   r   r   r   r   r   r   r   r   r   r   r   )rP   r   r   r   md_routero   r   s          r4   __call___MetaDataReader.__call__  s    7MM$++-=-?@/1A1ABB%%6%11%%{ #.#'&&/ ; ""m3		$..w78##}4 ,,T->->	J,WEJ$+yM%  s   DD..
D<)r   r   N)r[   r\   r]   r^   r   r   rL   r  r  r   r   r   r  r_   ry   rD   r4   r   r   Q  s@    *@ NC N4x'7'7 4D 4l $ rD   r   r   r   c                     [        U S9" US9$ )a  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 `ds_detect` 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   s     r4   r   r     s    F {3# rD   c                 8    [         R                  " U [        5      $ rT   )r   list_from_dependsdatasources)dependss    r4   get_datasource_listr    s    $$Wk::rD   __main__z*Query LXD metadata and emit a JSON object.)descriptionr   rT   )T)F__doc__loggingr   rU   r   r   enumr   r   json.decoderr   typingr   r   r   r	   r
   r   r   r  requests.adaptersr   urllib3.connectionr   urllib3.connectionpoolr   	cloudinitr   r   r   r   r   cloudinit.netr   	getLoggerr[   r+   rn   r   r   r   r   r5   rC   rF   rc   rk   r   r   r   r   r  r   r   Responser   r   r   r   r   DEP_FILESYSTEMr
  r  argparser  ArgumentParserparser
parse_argsprint
json_dumpsry   rD   r4   <module>r"     s    	     ( @ @ @  ) . 5 D D +!! 
 (!1+!+% c 6 !%#
49
#	#s(^#L,> ,6- 6	9{ 	9c d :f0G&& f0T ;?$'370 ;?$'37:'4 'N Nd ."."2"2%%% 
%T W++-.; zBK$$=F
	  \=M=M!NO rD   