U
    Ó‡g`  ã                   @   s   d dl Z d dlZd dlZd dlmZmZ d dlmZ d dlmZm	Z	m
Z
 d dlmZmZmZ d dlmZ d dlmZ e e¡Zg g dd	d
œZG dd„ de
ƒZdd„ Zejddd�dd„ ƒZdd„ Zdd„ Zd(eeeeef f dœdd„Zdd„ Zdd„ Z dd „ Z!d!d"„ Z"d#d$„ Z#d)d&d'„Z$dS )*é    N)ÚcopyÚdeepcopy)ÚIPv4Network)ÚDictÚListÚ	TypedDict)Ú	lifecycleÚsubpÚutil)Únet_prefix_to_ipv4_mask)ÚSimpleTableÚ F©Úipv4Úipv6ÚhwaddrÚupc                   @   s6   e Zd ZU eed< eed< ee ed< ee ed< dS )Ú	Interfacer   r   r   r   N)Ú__name__Ú
__module__Ú__qualname__ÚboolÚ__annotations__Ústrr   Údict© r   r   ú3/usr/lib/python3/dist-packages/cloudinit/netinfo.pyr   ,   s   
r   c              	   C   sP  t  | ¡}i }|D �]6}d|kr(|d ng }| d¡dkrB|d nd}|td|koXd|kƒg g dœ}| d	g ¡D ]Ì}| d
¡dkrÜd|kr¢ttd|d › �ƒjƒnd}| dd¡|| dd¡| dd¡dœ}	|d  |	¡ qp|d
 dkrp| dd¡}
|
�r| d¡�s|
› d| dd¡› �}
|
| dd¡dœ}	|d  |	¡ qp|||d < q|S )a&  Get network device dicts from ip route and ip link info.

    ipaddr_json: Output string from 'ip --json addr' command.

    Returns a dict of device info keyed by network device name containing
    device configuration values.

    Raises json.JSONDecodeError if json could not be decoded
    ÚflagsÚ	link_typeÚetherÚaddressr   ÚUPÚLOWER_UP)r   r   r   r   Z	addr_infoZfamilyÚinetÚ	prefixlenz0.0.0.0/ZlocalÚ	broadcastÚscope)ÚipÚmaskÚbcastr&   r   Úinet6ú/é@   )r'   Úscope6r   Zifname)ÚjsonÚloadsÚgetr   r   r   ÚnetmaskÚappend)Zipaddr_jsonZipaddr_dataÚdevsÚdevr   r    Zdev_infoÚaddrr(   Zparsed_addrr'   r   r   r   Ú_netdev_info_iproute_json3   s@    


üÿý


ü
þr6   z22.1zqRequired by old iproute2 versions that don't support ip json output. Consider upgrading to a more recent version.)Zdeprecated_versionZextra_messagec                 C   s¬  i }d}t |  ¡ ƒD �]�\}}t d|¡}|rz| d¡ ¡  d¡d }| d¡ d¡}g g dtd	|kold
|kƒdœ||< qd|krºt d|¡}|s¢t 	d||¡ q|| d  
| ¡ ¡ qd|k�rHt d|¡}|sät 	d||¡ q| ¡ }| d¡}| d¡\}	}
}|�sd}|| d  
|	|d �r0|d ndt|ƒ|d dœ¡ qd|krt d|¡}|�srt 	d||¡ q| d¡dk�r–| d¡|| d< nd|| d< qqq|S )zó
    @param ipaddr_out: Output string from 'ip addr show' command.

    @returns: A dict of device info keyed by network device name containing
              device configuration values.
    @raise: TypeError if ipaddr_out isn't a string.
    Nz.^\d+:\s(?P<dev>[^:]+):\s+<(?P<flags>\S+)>\s+.*r4   ú@r   r   ú,r   r!   r"   r   r*   z?\s+inet6\s(?P<ip>\S+)(\s(peer\s\S+))?\sscope\s(?P<scope6>\S+).*z*Could not parse ip addr show: (line:%d) %sr   r#   zd\s+inet\s(?P<cidr4>\S+)(\smetric\s(?P<metric>\d+))?(\sbrd\s(?P<bcast>\S+))?\sscope\s(?P<scope>\S+).*Úcidr4r+   Ú32r   r)   r&   )r'   r)   r(   r&   Úlinkz-\s+link/(?P<link_type>\S+)\s(?P<hwaddr>\S+).*r   r   r   )Ú	enumerateÚ
splitlinesÚreÚmatchÚgroupÚlowerÚsplitr   ÚLOGÚwarningr2   Ú	groupdictÚpopÚ	partitionr   )Ú
ipaddr_outr3   Zdev_nameZnumÚlineÚmr   r?   r9   r5   Ú_Úprefixr   r   r   Ú_netdev_info_iproutei   s„    üü  ÿ
û  ÿ
üÿ ÿ  ÿrM   c           
      C   sz  i }|   ¡ D �]f}t|ƒdkr q|d dkrb| ¡ d }| d¡rN|d d… }||krbttƒ||< | ¡  ¡  ¡ }t|ƒdkršt 	d|d ¡ršd|| d< t
t|ƒƒD �]Ê}|| d	krì||d   d
¡\}}|| d  |t|ƒdœ¡ q¦|| dk�r||d  || d d d< q¦|| dk�r<||d  || d< q¦|| dk�rœ||d  dk�r||| d  d||d  i¡ n|| d  d||d  i¡ q¦|| dk�rä|| d d d d
 ||d   }||| d d d< q¦||  d¡�r||  d¡|| d d d< q¦|| dkr¦t d||d  ¡}	|	�rV|	 d¡|| d d d< q¦||d  || d d d< q¦q|S )Nr   ©ú	ú ú:éÿÿÿÿé   zflags=[x\d]+<up.*>Tr   r#   r+   r   )r'   r(   r%   r)   zaddress:r   r*   úaddr:r   r'   é   r$   úscope:r-   Úscopeidú	.*<(\S+)>)r=   ÚlenrB   Úendswithr   ÚDEFAULT_NETDEV_INFOrA   Ústripr>   ÚsearchÚranger2   r   Ú
startswithÚlstripr?   r@   )
Úifconfig_datar3   rI   ÚcurdevÚtoksÚiZnetworkZnet_bitsÚaddr6Úresr   r   r   Ú_netdev_info_ifconfig_netbsd¼   sN    
ÿ  $  rg   c                 C   s   i }|   ¡ D �]}t|ƒdkr q|d dkrb| ¡ d }| d¡rN|d d… }||krbttƒ||< | ¡  ¡  ¡ }|d dkrŒd|| d< n(t|ƒdkr´t 	d|d ¡r´d|| d< t
t|ƒƒD �]V}|| d	krø|| d
  d||d   d¡i¡ qÀ||  d¡�r(||  d¡|| d
 d d< qÀ|| dk�rT||d  || d
 d d< qÀ||  d¡�r„||  d¡|| d
 d d< qÀ|| dk�r°||d  || d
 d d< qÀ|| dk�sÌ|| dk�râ||d  || d< qÀ|| dk�rB||d  dk�r"|| d  d||d  i¡ n|| d  d||d  i¡ qÀ|| dk�rŠ|| d d d d ||d   }||| d d d< qÀ||  d¡�rº||  d¡|| d d d< qÀ|| dkrÀt d||d  ¡}|�rü| d¡|| d d d< qÀ||d  || d d d< qÀq|S )Nr   rN   rQ   rR   r   TrS   zflags=\d+<up,r#   r   r'   rT   zbcast:r)   r%   zmask:r(   r1   r   r   r*   r   rU   r$   r+   rV   r-   rW   rX   )r=   rY   rB   rZ   r   r[   rA   r\   r>   r]   r^   r2   r`   r_   r?   r@   )ra   r3   rI   rb   rc   rd   re   rf   r   r   r   Ú_netdev_info_ifconfigì   s\    
ÿ    $  rh   )Úreturnc                    sþ   i }t  ¡ r0tjddgddgd�\}}t|ƒ}n˜t d¡r�z t dddg¡\}}t|ƒ}W qÈ tjk
rŒ   t ddd	g¡\}}t|ƒ}Y qÈX n8t d¡r¾tjddgddgd�\}}t|ƒ}n
t	 
d
¡ | dkrÔ|S tttf‰d‡ ‡fdd„	‰ ˆ || d� |S )af  return the instance's interfaces and interface data

    includes, interface name, link state, hardware address, and lists of ipv4
    and ipv6 addresses

    example output:
    {
    'lo': {
        'up': True,
        'hwaddr': '',
        'ipv4': [
        {
            'bcast': '',
            'ip': '127.0.0.1',
            'mask': '255.0.0.0',
            'scope': 'host',
        }],
        'ipv6': [{'ip': '::1/128', 'scope6': 'host'}],
    },
    'lxdbr0': {
        'up': True
        'hwaddr': '00:16:3e:fa:84:30',
        'ipv4': [{
            'bcast': '',
            'ip': '10.161.80.1',
            'mask': '255.255.255.0',
            'scope': 'global',
        }],
        'ipv6': [
            {'ip': 'fd42:80e2:4695:1e96::1/64', 'scope6': 'global'},
            {'ip': 'fe80::216:3eff:fefa:8430/64', 'scope6': 'link'},
        ]
    },
    }

    Zifconfigz-ar   rS   ©Zrcsr'   z--jsonr5   Zshowz>Could not print networks: missing 'ip' and 'ifconfig' commandsr   ©r   ó    c                    sl   t | tƒr|  ¡ }n t | ttfƒr,t| ƒ}ntdƒ‚|D ].\}}||krR|| |< q8t |ˆƒr8ˆ ||ƒ q8dS )zQRecursively replace 'empty_vals' in data (dict, tuple, list)
        with new_valzUnexpected input to fillN)Ú
isinstancer   ÚitemsÚtupleÚlistr<   Ú	TypeError)ÚdataÚnew_valZ
empty_valsZmyiterÚkeyÚval©ÚfillZrecurse_typesr   r   rw   g  s    




znetdev_info.<locals>.fill)rs   )r   rk   )r
   Z	is_NetBSDr	   rg   Úwhichr6   ÚProcessExecutionErrorrM   rh   rC   rD   r   ro   rp   )Úemptyr3   Z	ifcfg_outÚ_errrH   r   rv   r   Únetdev_info%  s.    '



ÿ
r|   c                 C   s´  i }g |d< g |d< |   ¡ }dddddddœ}|D �].}t|ƒ}|sFq2| ¡ }dg}|d dkrrd|d	< d|d
< n^d|d kr’|d  d¡\}}	n"|d }d}	| d¡ t|	ƒ|d
< ||d	< t|	ƒ|d
< d|d< tt|ƒƒD ]h}
||
 dk�r
||
d  |d< | dd¡ ||
 dk�r(||
d  |d< ||
 dkrÜ||
d  |d< qÜd |¡|d< |d  |¡ q2z(t	j	dddddddgddgd�\}}W n t	j
k
�r¦   Y �n
X |  ¡ }|D ]ú}i }|�sÆ�q´| ¡ }|d dk�rîd|d	< d|d< n|d |d	< d |d< d|d< tt|ƒƒD ]†}
||
 dk�r@||
d  |d< d|d< ||
 dk�r^||
d  |d< ||
 dk�r|||
d  |d< ||
 d!k�r|d d" |d< �q|d  |¡ �q´|S )#aP  
    Get network route dicts from ip route info.

    @param iproute_data: Output string from ip route command.

    @returns: A dict containing ipv4 and ipv6 route entries as lists. Each
              item in the list is a route dictionary representing destination,
              gateway, flags, genmask and interface information.
    r   r   r   )Údestinationr   ÚgatewayÚgenmaskÚifaceÚmetricÚUr   Údefaultú0.0.0.0r}   r   r+   r:   ÚHr~   ZviarS   ÚGr4   r€   r�   r   r'   z	--onelinez-6Úrouterp   ÚtableÚallrj   z::/0ZUGú::ZexpiresÚe)r=   r   rB   r2   r   r^   rY   ÚinsertÚjoinr	   ry   )Ziproute_dataÚroutesÚentriesZdefault_route_entryrI   Úentryrc   r   r5   Zcidrrd   Ziproute_data6Ú_err6Úentries6r   r   r   Ú_netdev_route_info_iproute{  sŒ    ú


þ
r“   c           	   
   C   s,  i }g |d< g |d< |   ¡ }|D ]Ô}|s*q | ¡ }t|ƒdk s |d dks |d dks |d dks |d dks |d d	kr|q t|ƒd
k r°| d¡ | d¡ |d |d< d|d< |d |d |d |d |d |d |d |d dœ}|d  |¡ q z$tjdddddgddgd�\}}W n tjk
�r2   Y nöX |  ¡ }|D ]æ}|�sN�q@| ¡ }t|ƒdk �s@|d dk�s@|d dk�s@|d dk�s@|d dk�s@|d dk�r®�q@|d |d |d |d |d |d |d dœ}|d dk�rð�q@|d  d¡�rt d d!|d ¡|d< |d  |¡ �q@|S )"Nr   r   é   r   ZKernelÚDestinationZInternetZ	Internet6ZRoutingé   ú-é   é   rS   rU   é   é   )r}   r~   r   r   r�   ÚrefÚuser€   Únetstatz-Ar*   ú--routeú	--numericrj   ZProtoZActive)r}   r~   r   r�   rœ   r�   r€   r€   Úlor}   z/128z\/128$r   )	r=   rB   rY   r2   r	   ry   rZ   r>   Úsub)	Z
route_datarŽ   r�   rI   rc   r�   Zroute_data6r‘   r’   r   r   r   Ú_netdev_route_info_netstatÓ  sž    	
ÿ
þ
ý
ü
û
ú

ø
 ÿ
ÿ
þ
ý
ü
û
úù
  ÿr£   c                  C   sn   i } t  d¡r.t   ddddg¡\}}t|ƒ} n<t  d¡r`t j ddddgd	d
gd�\}}t|ƒ} n
t d¡ | S )Nr'   z-or‡   rp   rž   rŸ   r    z--extendr   rS   rj   z;Could not print routes: missing 'ip' and 'netstat' commands)r	   rx   r“   r£   rC   rD   )rŽ   Ziproute_outr{   Z	route_outr   r   r   Ú
route_info(  s    



 ÿ

ÿr¤   c                  C   sŽ  g } d}zt |d�}W nD tk
rZ } z$|  t djt|ƒd�dd¡¡ W 5 d }~X Y �n&X |sddS dd	d
dddg}t|ƒ}t| 	¡ ƒD ]¾\}}| 
d¡D ]2}| ||d |d |d | 
d|¡|d f¡ qš| 
d¡D ].}| ||d |d || 
d|¡|d f¡ qØt| 
d¡ƒt| 
d¡ƒ dkrˆ| ||d ||||d f¡ qˆ| ¡ }	tt|	 ¡ td�ƒ}
t dd|
¡}|  ||	g¡ d | ¡d S )NÚ.)rz   z Net device info failed ({error})©Úerrorú!éP   Ú
ZDeviceZUpZAddressZMaskZScopez
Hw-Addressr   r   r'   r(   r&   r   r   r-   r   ©rt   zNet device infoú+)r|   Ú	Exceptionr2   r
   ÚcenterÚformatr   r   Úsortedrn   r0   Úadd_rowrY   Ú
get_stringÚmaxr=   Úextendr�   )Úlinesrz   Znetdevr‹   ZfieldsZtblr4   rr   r5   Znetdev_sÚmax_lenÚheaderr   r   r   Únetdev_pformat;  s\    ýÿ
úÿ

úÿ
 ÿr¸   c                  C   sF  g } z
t ƒ }W nT tk
rb } z4|  t djt|ƒd�dd¡¡ t td| ¡ W 5 d }~X Y �nÖX | 	d¡�rHddd	d
ddg}t
|ƒ}t| 	d¡ƒD ]x\}}t|ƒ}z2| ||d | 	dd¡|d |d |d g¡ W q– tk
�r } zt td| ¡ W 5 d }~X Y q–X q–| ¡ }tt| ¡ td�ƒ}	t dd|	¡}
|  |
|g¡ | 	d¡�r8ddd	ddg}t
|ƒ}t| 	d¡ƒD ]†\}}t|ƒ}|d dk�rš�qxz,| ||d | 	dd¡|d |d g¡ W n4 tk
�rú } zt td| ¡ W 5 d }~X Y nX �qx| ¡ }tt| ¡ td�ƒ}	t dd|	¡}
|  |
|g¡ d | ¡d S )NzRoute info failed ({error})r¦   r¨   r©   zRoute info failed: %sr   ZRouter•   ZGatewayZGenmaskr   ZFlagsr}   r~   r„   r   r€   r   zRoute info formatting error: %sr«   zRoute IPv4 infor¬   r   r¡   rŠ   zRoute IPv6 inforª   )r¤   r­   r2   r
   r®   r¯   r   ZlogexcrC   r0   r   r<   r±   ÚKeyErrorr²   rY   r³   r=   r´   r�   )rµ   rŽ   r‹   Z	fields_v4Ztbl_v4ÚnÚrZroute_idZroute_sr¶   r·   Z	fields_v6Ztbl_v6r   r   r   Úroute_pformato  s†    
  ÿÿ$ú
úÿ
$û
ûÿ	&r¼   ú	ci-info: c                 C   sz   g }t ƒ  ¡ }| r0|D ]}| d| |f ¡ qn
| |¡ tƒ  ¡ }| rf|D ]}| d| |f ¡ qLn
| |¡ d |¡S )Nz%s%srª   )r¸   r=   r2   r´   r¼   r�   )rL   rµ   Znetdev_linesrI   Zroute_linesr   r   r   Ú
debug_info¸  s    



r¾   )r   )r½   )%r.   Zloggingr>   r   r   Z	ipaddressr   Útypingr   r   r   Z	cloudinitr   r	   r
   Zcloudinit.net.network_stater   Zcloudinit.simpletabler   Z	getLoggerr   rC   r[   r   r6   Zdeprecate_callrM   rg   rh   r   r|   r“   r£   r¤   r¸   r¼   r¾   r   r   r   r   Ú<module>   s:   
6þ
N0: ÿþVXU4I