o
    f$                     @   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 )KlibcNetworkConfigSourcezInitramfsNetworkConfigSource 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|||
  |	|
 < qg }dD ]}||| }|rt|dr||||   q|r||	d< |d}|rd|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 )zDecode 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
`
