o
    f_                     @   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dd Zejddddd Zdd Zdd Z	d&deeeee
ee	eeef  f f f f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Union)	lifecyclesubputil)net_prefix_to_ipv4_mask)SimpleTable Fipv4ipv6hwaddrupc              	   C   sJ  t | }i }|D ]}d|v r|d ng }|ddkr |d nd}|td|v o+d|v g g d}|d	g D ]d}|d
dkrmd|v rPttd|d  jnd}|dd||dd|ddd}	|d |	 q7|d
 dkr|dd}
|
r|ds|
 d|dd }
|
|ddd}	|d |	 q7|||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   	addr_infofamilyinet	prefixlenz0.0.0.0/local	broadcastscope)ipmaskbcastr   r   inet6/@   )r    scope6r   ifname)jsonloadsgetboolstrr   netmaskappend)ipaddr_jsonipaddr_datadevsdevr   r   dev_infoaddrr!   parsed_addrr     r6   3/usr/lib/python3/dist-packages/cloudinit/netinfo.py_netdev_info_iproute_json,   sB   





r8   z22.1zqRequired by old iproute2 versions that don't support ip json output. Consider upgrading to a more recent version.)deprecated_versionextra_messagec                 C   s  i }d}t |  D ]\}}td|}|r<|d dd }|dd}g g dtd	|v o5d
|v d||< q
d|v r\td|}|sPt	d|| q
|| d 
|  q
d|v rtd|}|spt	d|| q
| }|d}|d\}	}
}|sd}|| d 
|	|d r|d ndt||d d q
d|v rtd|}|st	d|| q
|ddkr|d|| d< q
d|| d< 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+.*r2   @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warningr.   	groupdictpop	partitionr   )
ipaddr_outr1   dev_namenumlinemr   rC   r=   r4   _prefixr6   r6   r7   _netdev_info_iprouteb   sv   
rS   c           
      C   sp  i }|   D ].}t|dkrq|d dvr1| d }|dr'|d d }||vr1tt||< |   }t|dkrMt	d|d rMd|| d< t
t|D ]}|| d	kru||d  d
\}}|| d |t|d qS|| dkr||d  || d d d< qS|| dkr||d  || d< qS|| dkr||d  dkr|| d d||d  i qS|| d d||d  i qS|| dkr|| d d d d
 ||d   }||| d d d< qS|| dr|| d|| d d d< qS|| dkr4td||d  }	|	r&|	d|| d d d< qS||d  || d d d< qSq|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+)>)rA   lenrF   endswithr   DEFAULT_NETDEV_INFOrE   striprB   searchranger.   r   
startswithlstriprC   rD   )
ifconfig_datar1   rO   curdevtoksinetworknet_bitsaddr6resr6   r6   r7   _netdev_info_ifconfig_netbsd   sR   
  $ ro   c                 C   s  i }|   D ]}t|dkrq|d dvr1| d }|dr'|d d }||vr1tt||< |   }|d dkrFd|| d< nt|dkrZt	d|d rZd|| d< t
t|D ]&}|| d	kr||| d
 d||d  di q`|| dr|| d|| d
 d d< q`|| dkr||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r||d  dkr|| d d||d  i q`|| d d||d  i q`|| dkr?|| d d d d ||d   }||| d d d< q`|| drW|| d|| d d d< q`|| dkrtd||d  }|ry|d|| d d d< q`||d  || d d d< q`q|S )Nr   rT   rW   rX   r   TrY   zflags=\d+<up,r   r   r    rZ   zbcast:r"   r   zmask:r!   r-   r   r   r#   r   r[   r   r$   r\   r&   r]   r^   )rA   r_   rF   r`   r   ra   rE   rb   rB   rc   rd   r.   rf   re   rC   rD   )rg   r1   rO   rh   ri   rj   rm   rn   r6   r6   r7   _netdev_info_ifconfig   s`   
    $  rp   returnc                    s   i }t  rtjddgddgd\}}t|}nHtdrDztg d\}}t|}W n3 tjyC   tg d\}}t|}Y nw tdr[tjddgddgd\}}t|}nt	
d	 | d
krf|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'},
        ]
    },
    }

    ifconfigz-ar   rY   rcsr    )r    z--jsonr4   )r    r4   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 ]\}}||v r)|| |< qt |r3 || qdS )zQRecursively replace 'empty_vals' in data (dict, tuple, list)
        with new_valzUnexpected input to fillN)
isinstancedictitemstuplelistr@   	TypeError)datanew_val
empty_valsmyiterkeyvalfillrecurse_typesr6   r7   r   `  s   





znetdev_info.<locals>.fill)r   N)r   rv   )r
   	is_NetBSDr	   ro   whichr8   ProcessExecutionErrorrS   rp   rG   rH   ry   r{   r|   )emptyr1   	ifcfg_out_errrL   r6   r   r7   netdev_info  s0   '




r   c                 C   s  i }g |d< g |d< |   }ddddddd}|D ]}t|}|s"q| }dg}|d dkr8d|d	< d|d
< n/d|d v rH|d d\}}	n|d }d}	|d t|	|d
< ||d	< t|	|d
< d|d< tt|D ]2}
||
 dkr||
d  |d< |dd ||
 dkr||
d  |d< ||
 dkr||
d  |d< qmd||d< |d | qzt	j	g dddgd\}}W n t	j
y   Y |S w |  }|D ]x}i }|sq| }|d dkrd|d	< d|d< n|d |d	< d|d< d|d< tt|D ]B}
||
 dkr||
d  |d< d|d< ||
 dkr"||
d  |d< ||
 dkr1||
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   viarY   Gr2   r   r   r   )r    z	--onelinez-6router|   tableallrs   z::/0UG::expirese)rA   r   rF   r.   r   rd   r_   insertjoinr	   r   )iproute_dataroutesentriesdefault_route_entryrO   entryri   r   r4   cidrrj   iproute_data6_err6entries6r6   r6   r7   _netdev_route_info_iproutet  s   


r   c           	   
   C   s
  i }g |d< g |d< |   }|D ]j}|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 rX|d |d |d |d< d|d< |d |d |d |d |d |d |d |d d}|d | qztjg dddgd\}}W n tjy   Y |S w |  }|D ]f}|sq| }t|dk s|d dks|d dks|d dks|d dks|d dkrq|d |d |d |d |d |d |d d}|d dkrq|d drtdd|d |d< |d | q|S )Nr   r      r   KernelDestinationInternet	Internet6Routing   -      rY   r[         )r   r   r   r   r   refuser   )netstatz-Ar#   --route	--numericrs   ProtoActive)r   r   r   r   r   r   r   r   lor   z/128z\/128$r   )	rA   rF   r_   r.   r	   r   r`   rB   sub)	
route_datar   r   rO   ri   r   route_data6r   r   r6   r6   r7   _netdev_route_info_netstat  s   	


"

r   c                  C   sj   i } t drt  g d\}}t|} | S t dr.t j g dddgd\}}t|} | S td | S )	Nr    )r    z-or   r|   r   )r   r   r   z--extendr   rY   rs   z;Could not print routes: missing 'ip' and 'netstat' commands)r	   r   r   r   rG   rH   )r   iproute_outr   	route_outr6   r6   r7   
route_info!  s   


r   c                  C   s  g } d}zt |d}W n" ty- } z| tdjt|ddd W Y d }~nd }~ww |s2dS g d}t|}t|	 D ]_\}}|
d	D ]}|||d
 |d |d |
d||d f qI|
dD ]}|||d
 |d ||
d||d f qht|
dt|
d	 dkr|||d
 ||||d f q@| }	tt|	 td}
tdd|
}| ||	g d| d S )N.)r   z Net device info failed ({error})error!P   
)DeviceUpAddressMaskScopez
Hw-Addressr   r   r    r!   r   r   r   r&   r   r   zNet device info+)r   	Exceptionr.   r
   centerformatr,   r   sortedrz   r*   add_rowr_   
get_stringmaxrA   extendr   )linesr   netdevr   fieldstblr2   r~   r4   netdev_smax_lenheaderr6   r6   r7   netdev_pformat4  sb   	


 
r   c                  C   s,  g } zt  }W n* ty1 } z| tdjt|ddd ttd|  W Y d }~nd }~ww |	drg d}t
|}t|	dD ];\}}t|}z|||d |	d	d
|d |d |d g W qF ty } zttd|  W Y d }~qFd }~ww | }tt| td}	tdd|	}
| |
|g |	drg d}t
|}t|	dD ]?\}}t|}|d dkrqz|||d |	d	d|d |d g W q ty } zttd|  W Y d }~qd }~ww | }tt| td}	tdd|	}
| |
|g d| d S )NzRoute info failed ({error})r   r   r   zRoute info failed: %sr   )Router   GatewayGenmask	InterfaceFlagsr   r   r   r   r   r   zRoute info formatting error: %sr   zRoute IPv4 infor   r   )r   r   r   r   r   r   r   zRoute IPv6 infor   )r   r   r.   r
   r   r   r,   logexcrG   r*   r   r@   r   KeyErrorr   r_   r   rA   r   r   )r   r   r   	fields_v4tbl_v4nrroute_idroute_sr   r   	fields_v6tbl_v6r6   r6   r7   route_pformath  sx   




	r   	ci-info: c                 C   sz   g }t   }| r|D ]}|d| |f  qn|| t  }| r3|D ]}|d| |f  q&n|| d|S )Nz%s%sr   )r   rA   r.   r   r   r   )rR   r   netdev_linesrO   route_linesr6   r6   r7   
debug_info  s   




r   )r   )r   )$r(   loggingrB   r   r   	ipaddressr   typingr   r   r   	cloudinitr   r	   r
   cloudinit.net.network_stater   cloudinit.simpletabler   	getLogger__name__rG   ra   r8   deprecate_callrS   ro   rp   r,   r   r   r   r   r   r   r   r6   r6   r6   r7   <module>   s:   

6
N0:&
VXU4I