U
    LdD$                     @   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edddZejedddZ	dS )InitramfsNetworkConfigSourcezBABC for net config sources that read config written by initramfsesreturnc                 C   s   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   s    z*InitramfsNetworkConfigSource.is_applicablec                 C   s   dS )z;Render a v1 network config from the initramfs configurationNr	   r
   r	   r	   r   render_config"   s    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edddZed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   sp   || _ || _|| _| j d kr$t | _ | jd kr8t | _| jd krli | _t D ]}t|d}|rN|| j|< qNd S )Naddress)_files
_mac_addrs_cmdline_get_klibc_net_cfg_filesr   get_cmdliner   r   )r   r   r   r   kZmac_addrr	   r	   r   __init__/   s    





z!KlibcNetworkConfigSource.__init__r   c                 C   s<   | j r8t| jD ]}|dr dS qtjtr8d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kri }t | }zd|kr(|d n|d }W n, tk
r^ } ztd|W 5 d}~X Y nX |d|d}|s|drd}nd	}|d
krtd| d|g d}||kr|| |d< dD ]}|d |krq||d |}|d	krd}|dd}	|dkr||d  |	d< dD ](}
||
 |kr|||
  |	|
 < qg }dD ]<}||| }|rLt|drL||||   qL|r||	d< |d}|rd|kr|	d|	d< n|	 |	d< |d |	 q||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).
    note that IPV6PROTO is also written by newer code 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
    NZDEVICEZDEVICE6z&no 'DEVICE' or 'DEVICE6' entry in dataZPROTOZ	IPV6PROTOfilenamedhcpnone)r.   r-   Zdhcp6zUnexpected value for PROTO: %sZphysical)typenamesubnetsmac_address)ZIPV4ZIPV6ZADDRZstaticZmanual)r/   Zcontrolr   )ZNETMASKZ	BROADCASTZGATEWAY)ZDNS0ZDNS1z:.0Zdns_nameserversZDOMAINSEARCH,Z
dns_searchr1   )
r   Zload_shell_contentKeyError
ValueErrorgetlowerlenstripappendr"   )Zcontentr*   datar0   eprotoZifaceZpreZ	cur_protoZsubnetkeyZdnsZnskeynssearchr	   r	   r   _klibc_to_config_entry^   s\    






rA   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 krt  } g }i }| D ]}tt||d\}}||kr|| d }|d|dkrtdj|d|| d |d|dd|d |d  || d 	| q|g|d	||< |	| q|d
dS )N)r*   entryr2   zedevice '{name}' was defined multiple times ({files}) but had differing mac addresses: {old} -> {new}. r)   )r0   r)   oldnewr1   )r)   rC      )configversion)
r   rA   r   Z	load_filer6   r5   formatjoinextendr:   )r)   r*   entriesnamesZcfg_filer0   rC   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   )Zsrc_clsZ
cfg_sourcer	   r	   r   read_initramfs_config   s    rQ   c              
   C   s   t | p}d }zVz(tjd|d}| W W :W  5 Q R  S  tk
rb   |  Y W W  5 Q R  S X W 5 |rt|  X W 5 Q R X d S )Nrb)modeZfileobj)ioBytesIOclosegzipZGzipFilereadIOError)blobZiobufZgzfpr	   r	   r   _decomp_gzip   s    r[   c              	   C   s>   zt | }W n& ttfk
r4   td|  Y dS X t|S )zDecode a string base64 encoding, if gzipped, uncompress as well

    :return: decompressed unencoded string of the data or empty string on
       unencoded data.
    z`Expected base64 encoded kernel commandline parameter network-config. Ignoring network-config=%s. )base64Z	b64decode	TypeErrorr5   LOGerrorr[   )r;   rZ   r	   r	   r   _b64dgz   s    ra   c                 C   sj   | d krt  } d| krfd }|  D ]}|dr$|ddd }q$|rf|tkrXddiS t t|S d S )Nznetwork-config==rG   rH   r   )r   r   r"   r#   &KERNEL_CMDLINE_NETWORK_CONFIG_DISABLEDZ	load_yamlra   )ZcmdlineZdata64tokr	   r	   r   read_kernel_cmdline_config  s    
re   )N)NN)N)r   r]   rB   rW   rT   Zloggingr$   r!   Z	cloudinitr   Zcloudinit.netr   r   r'   rc   Z	getLoggerr   r_   ABCMetar   r   rP   rA   r   r+   rQ   r[   ra   re   r	   r	   r	   r   <module>   s,   
4
]
