o
    x[hƒ$  ã                   @   sÚ   d dl Z d dlZd dl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	 d dl
mZmZ dZdZe e¡ZG dd„ de jd�ZG d	d
„ d
eƒZegZddd„Zdd„ Zddd„Zdd„ Zdd„ Zdd„ Zddd„ZdS )é    N)Úutil)Úget_devicelistÚread_sys_net_safez#/run/initramfs/open-iscsi.interfaceÚdisabledc                   @   s8   e Zd ZdZejdefdd„ƒZejdefdd„ƒZ	dS )ÚInitramfsNetworkConfigSourcezBABC for net config sources that read config written by initramfsesÚreturnc                 C   ó   dS )zAIs this initramfs config source applicable to the current system?N© ©Úselfr	   r	   ú7/usr/lib/python3/dist-packages/cloudinit/net/cmdline.pyÚis_applicable   ó    z*InitramfsNetworkConfigSource.is_applicablec                 C   r   )z;Render a v1 network config from the initramfs configurationNr	   r
   r	   r	   r   Úrender_config"   r   z*InitramfsNetworkConfigSource.render_configN)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚabcÚabstractmethodÚboolr   Údictr   r	   r	   r	   r   r      s    r   )Ú	metaclassc                   @   s6   e Zd ZdZd
dd„Zdefdd„Zdefdd	„ZdS )ÚKlibcNetworkConfigSourcezñInitramfsNetworkConfigSource for klibc initramfs (i.e. Debian/Ubuntu)

    Has three parameters, but they are intended to make testing simpler, _not_
    for use in production code.  (This is indicated by the prepended
    underscores.)
    Nc                 C   st   || _ || _|| _| j d u rtƒ | _ | jd u rt ¡ | _| jd u r6i | _tƒ D ]}t|dƒ}|r5|| j|< q'd S d S )NÚaddress)Ú_filesÚ
_mac_addrsÚ_cmdlineÚ_get_klibc_net_cfg_filesr   Úget_cmdliner   r   )r   r   r   r   ÚkÚmac_addrr	   r	   r   Ú__init__/   s    






€ûz!KlibcNetworkConfigSource.__init__r   c                 C   s<   | j rt | j¡D ]
}| d¡r dS q	tj t¡rdS dS )aD  
        Return whether this system has klibc initramfs network config or not

        Will return True if:
            (a) klibc files exist in /run, AND
            (b) either:
                (i) ip= or ip6= are on the kernel cmdline, OR
                (ii) an open-iscsi interface file is present in the system
        )zip=zip6=TF)	r   ÚshlexÚsplitr   Ú
startswithÚosÚpathÚexistsÚ_OPEN_ISCSI_INTERFACE_FILE)r   Úitemr	   r	   r   r   A   s   

ÿz&KlibcNetworkConfigSource.is_applicablec                 C   s   t | j| jd�S )N)ÚfilesÚ	mac_addrs)Úconfig_from_klibc_net_cfgr   r   r
   r	   r	   r   r   T   s   þz&KlibcNetworkConfigSource.render_config)NNN)	r   r   r   r   r"   r   r   r   r   r	   r	   r	   r   r   '   s
    
r   c              
   C   sÔ  |du ri }t  | ¡}zd|v r|d n|d }W n ty* } ztdƒ|‚d}~ww | d| d¡¡}|s@| d¡r>d}nd	}|d
v rFd	}|dvrPtd| ƒ‚d|g dœ}||v r`|| |d< dD ]ƒ}|d |vrkqb| |d |¡}|d	kryd}|ddœ}	|dkrŠ||d  |	d< dD ]}
||
 |v rž|||
  |	|
 ¡ < qŒg }dD ]}| || ¡}|r¾t| d¡ƒr¾| |||  ¡ q£|rÞ||	d< | d¡}|rÞd|v rØ| 	d¡|	d< n| 	¡ |	d< |d  |	¡ qb||fS )a  Convert a klibc written shell content file to a 'config' entry
    When ip= is seen on the kernel command line in debian initramfs
    and networking is brought up, ipconfig will populate
    /run/net-<name>.cfg.

    The files are shell style syntax, and examples are in the tests
    provided here.  There is no good documentation on this unfortunately.

    DEVICE=<name> is expected/required and PROTO should indicate if
    this is 'none' (static) or 'dhcp' or 'dhcp6' (LP: #1621507) or 'static'
    or 'off' (LP: 2065787). Note that IPV6PROTO is also written to address
    the possibility of both ipv4 and ipv6 getting addresses.

    Full syntax is documented at:
    https://git.kernel.org/pub/scm/libs/klibc/klibc.git/plain/usr/kinit/ipconfig/README.ipconfig
    NÚDEVICEÚDEVICE6z&no 'DEVICE' or 'DEVICE6' entry in dataÚPROTOÚ	IPV6PROTOÚfilenameÚdhcpÚnone)ÚstaticÚoff)r4   r3   Údhcp6zUnexpected value for PROTO: %sÚphysical)ÚtypeÚnameÚsubnetsÚmac_address)ÚIPV4ÚIPV6ÚADDRr5   Úmanual)r9   Úcontrolr   )ÚNETMASKÚ	BROADCASTÚGATEWAY)ÚDNS0ÚDNS1z:.0Údns_nameserversÚDOMAINSEARCHú,Ú
dns_searchr;   )
r   Úload_shell_contentÚKeyErrorÚ
ValueErrorÚgetÚlowerÚlenÚstripÚappendr$   )Úcontentr,   Údatar:   ÚeÚprotoÚifaceÚpreÚ	cur_protoÚsubnetÚkeyÚdnsÚnskeyÚnsÚsearchr	   r	   r   Ú_klibc_to_config_entry^   sh   

€ÿ
ý
€€
r`   c                   C   s   t   d¡t   d¡ S )Nz/run/net-*.confz/run/net6-*.conf)Úglobr	   r	   r	   r   r   ¾   s   r   c              	   C   sØ   | d u rt ƒ } g }i }| D ]Y}tt |¡|d�\}}||v rY|| d }| d¡| d¡krFtdj|d || d ¡| d¡| d¡d�ƒ‚|d  |d ¡ || d  	|¡ q|g|d	œ||< | 	|¡ q|d
dœS )N)r,   Úentryr<   zedevice '{name}' was defined multiple times ({files}) but had differing mac addresses: {old} -> {new}.ú r+   )r:   r+   ÚoldÚnewr;   )r+   rb   é   )ÚconfigÚversion)
r   r`   r   Úload_text_filerN   rM   ÚformatÚjoinÚextendrR   )r+   r,   ÚentriesÚnamesÚcfg_filer:   rb   Úprevr	   r	   r   r-   Â   s2   

ÿûÿ	
r-   c                  C   s(   t D ]} | ƒ }| ¡ sq| ¡   S dS )a  
    Return v1 network config for initramfs-configured networking (or None)

    This will consider each _INITRAMFS_CONFIG_SOURCES entry in turn, and return
    v1 network configuration for the first one that is applicable.  If none are
    applicable, return None.
    N)Ú_INITRAMFS_CONFIG_SOURCESr   r   )Úsrc_clsÚ
cfg_sourcer	   r	   r   Úread_initramfs_configá   s   rt   c              	   C   sž   t  | ¡�@}d }z4ztjd|d�}| ¡ W W |r| ¡  W  d   ƒ S  ty<   |  Y W |r4| ¡  W  d   ƒ S w |rD| ¡  w w 1 sHw   Y  d S )NÚrb)ÚmodeÚfileobj)ÚioÚBytesIOÚgzipÚGzipFileÚreadÚcloseÚIOError)ÚblobÚiobufÚgzfpr	   r	   r   Ú_decomp_gzipó   s$   
÷÷
ÿør‚   c              	   C   s:   z
t  | ¡}W t|ƒS  ttfy   t d| ¡ Y dS w )z¦Decode a string base64 encoding, if gzipped, uncompress as well

    :return: decompressed unencoded string of the data or empty string on
       unencoded data.
    zaExpected base64 encoded kernel command line parameter network-config. Ignoring network-config=%s.Ú )Úbase64Ú	b64decodeÚ	TypeErrorrM   ÚLOGÚerrorr‚   )rT   r   r	   r	   r   Ú_b64dgz  s   	øýúr‰   c                 C   sj   | d u rt  ¡ } d| v r3d }|  ¡ D ]}| d¡r!| dd¡d }q|r3|tkr,ddiS t  t|ƒ¡S d S )Nznetwork-config=ú=rf   rg   r   )r   r   r$   r%   Ú&KERNEL_CMDLINE_NETWORK_CONFIG_DISABLEDÚ	load_yamlr‰   )ÚcmdlineÚdata64Útokr	   r	   r   Úread_kernel_cmdline_config  s   
€r�   )N)NN)r   r„   ra   rz   rx   Úloggingr&   r#   Ú	cloudinitr   Úcloudinit.netr   r   r)   r‹   Ú	getLoggerr   r‡   ÚABCMetar   r   rq   r`   r   r-   rt   r‚   r‰   r�   r	   r	   r	   r   Ú<module>   s.   
4
`
