o
    x[h‡-  ã                   @   st  d 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	m
Z
mZ ddlmZ ddlmZmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZ ddlmZ e e¡Z dZ!d$dd„Z"G dd„ dej#ƒZ$G dd„ de$ƒZ%de%ej&fiZ'dd„ Z(dede)fdd„Z*deddfdd„Z+d%dd„Z,dede-fdd „Z.d!d"„ Z/ed#kr¸e"ƒ  0¡ Z1e/e!e1ƒ dS dS )&z)Handle reconfiguration on hotplug events.é    N)Ú	reportingÚstagesÚutil)Úinstall_hotplug)Ú
EventScopeÚ	EventType)Úloggers)Úread_sys_net_safe)Úparse_net_config_data)Úevents)Ú
DataSourceÚDataSourceNotFoundException)ÚInitzhotplug-hookc                 C   sœ   | s	t jttd�} t| _| jdddddgd� | jdd	d
�}d|_|jddd� |jddd�}|jdddddd� |jddddddgd� |jddd� | S )a  Build or extend an arg parser for hotplug-hook utility.

    @param parser: Optional existing ArgumentParser instance representing the
        subcommand which will be extended to support the args of this utility.

    @returns: ArgumentParser with proper argument configuration.
    )ÚprogÚdescriptionz-sz--subsystemTzsubsystem to act onÚnet)ÚrequiredÚhelpÚchoiceszHotplug ActionÚhotplug_action)ÚtitleÚdestÚqueryz0Query if hotplug is enabled for given subsystem.)r   ÚhandlezHandle the hotplug event.z-dz	--devpathÚPATHzSysfs path to hotplugged device)r   Úmetavarr   z-uz--udevactionzSpecify action to take.ÚaddÚremoveÚenablez%Enable hotplug for a given subsystem.)	ÚargparseÚArgumentParserÚNAMEÚ__doc__r   Úadd_argumentÚadd_subparsersr   Ú
add_parser)ÚparserÚ
subparsersÚparser_handle© r)   úB/usr/lib/python3/dist-packages/cloudinit/cmd/devel/hotplug_hook.pyÚ
get_parser   sL   ûÿÿÿûûÿr+   c                   @   s`   e Zd Zdd„ Zejdd„ ƒZeejdd„ ƒƒZejde	fdd	„ƒZ
d
d„ Zdd„ Zdd„ ZdS )ÚUeventHandlerc                 C   s"   || _ || _|| _|| _|| _d S ©N)ÚidÚ
datasourceÚdevpathÚactionÚ
success_fn)Úselfr.   r/   r0   r1   r2   r)   r)   r*   Ú__init__R   s
   
zUeventHandler.__init__c                 C   ó   t ƒ ‚r-   ©ÚNotImplementedError©r3   r)   r)   r*   ÚapplyY   ó   zUeventHandler.applyc                 C   r5   r-   r6   r8   r)   r)   r*   Úconfig]   s   zUeventHandler.configÚreturnc                 C   r5   r-   r6   r8   r)   r)   r*   Údevice_detectedb   r:   zUeventHandler.device_detectedc                 C   sP   d }| j dkr
d}n| j dkrd}ntd| j  ƒ‚||  ¡ kr&td| j ƒ‚d S )Nr   Tr   FzUnknown action: %sz'Failed to detect %s in updated metadata)r1   Ú
ValueErrorr=   ÚRuntimeErrorr.   )r3   Údetect_presencer)   r)   r*   Údetect_hotplugged_devicef   s   

ÿÿz&UeventHandler.detect_hotplugged_devicec                 C   s   |   ¡ S r-   )r2   r8   r)   r)   r*   Úsuccesst   s   zUeventHandler.successc                 C   s,   | j  tjg¡}|std| j tjf ƒ‚|S )Nz&Datasource %s not updated for event %s)r/   Úupdate_metadata_if_supportedr   ÚHOTPLUGr?   )r3   Úresultr)   r)   r*   Úupdate_metadataw   s   ÿ
ÿÿzUeventHandler.update_metadataN)Ú__name__Ú
__module__Ú__qualname__r4   ÚabcÚabstractmethodr9   Úpropertyr;   Úboolr=   rA   rB   rF   r)   r)   r)   r*   r,   Q   s    
r,   c                       s>   e Zd Z‡ fdd„Zdd„ Zedd„ ƒZdefdd	„Z‡  Z	S )
Ú
NetHandlerc                    s*   t tj |¡dƒ}tƒ  |||||¡ d S )NÚaddress)r	   ÚosÚpathÚbasenameÚsuperr4   )r3   r/   r0   r1   r2   r.   ©Ú	__class__r)   r*   r4   „   s   zNetHandler.__init__c                 C   s‚   | j jj| jdd� tj | j¡}| j j ¡ }| j	dkr+| 
|¡s)td | j¡ƒ‚d S | j	dkr=| |¡s?td | j¡ƒ‚d S d S )NF)Úbring_upr   zFailed to bring up device: {}r   zFailed to bring down device: {})r/   ÚdistroÚapply_network_configr;   rP   rQ   rR   r0   Únetwork_activatorr1   Úbring_up_interfacer?   ÚformatÚbring_down_interface)r3   Úinterface_nameÚ	activatorr)   r)   r*   r9   ‰   s&   þ


ÿÿ


ÿþzNetHandler.applyc                 C   s   | j jS r-   )r/   Únetwork_configr8   r)   r)   r*   r;   ›   s   zNetHandler.configr<   c                    s<   t ˆ jƒ}‡ fdd„| ¡ D ƒ}t dˆ j|¡ t|ƒdkS )Nc                    s    g | ]}|  d ¡ˆ jkr|‘qS )Úmac_address)Úgetr.   )Ú.0Úifacer8   r)   r*   Ú
<listcomp>¡   s
    þz.NetHandler.device_detected.<locals>.<listcomp>zIfaces with ID=%s : %sr   )r
   r;   Úiter_interfacesÚLOGÚdebugr.   Úlen)r3   ÚnetstateÚfoundr)   r8   r*   r=   Ÿ   s   

þzNetHandler.device_detected)
rG   rH   rI   r4   r9   rL   r;   rM   r=   Ú__classcell__r)   r)   rT   r*   rN   ƒ   s    
rN   r   c              
   C   sR   zt | d }W n ty } ztd |¡ƒ|‚d }~ww tj| j| jtj	|d�S )Né   z4hotplug-hook: cannot handle events for subsystem: {})r/   ÚcfgÚevent_source_typeÚscope)
ÚSUBSYSTEM_PROPERTIES_MAPÚKeyErrorr?   r[   r   Úupdate_event_enabledr/   rm   r   rD   )Úhotplug_initÚ	subsystemro   Úer)   r)   r*   Ú
is_enabled¯   s$   ÿÿü€ÿürv   rs   rt   c                 C   sR   t  d¡ | jdd�}| tjg¡st  d|¡ d S t| |ƒs't  d|¡ d S |S )NzFetching datasourceÚtrust©Úexistingz*hotplug not supported for event of type %sz(hotplug not enabled for event of type %s)rf   rg   ÚfetchÚget_supported_eventsr   rD   rv   )rs   rt   r/   r)   r)   r*   Úinitialize_datasourceÁ   s   

r|   r<   c                 C   s°   t | |ƒ}|s	d S t| d }t d|¡ ||||| jd�}t ¡ }|jjs.t|||ƒ d S t ¡ | |jj	k rVt|||ƒ t d¡ t 
|jj¡ t ¡ | |jj	k s8d S d S )Nr   zCreating %s event handler)r/   r0   r1   r2   z>Gathering network configuration again due to IMDS limitations.)r|   rp   rf   rg   Ú_write_to_cacheÚtimeÚhotplug_retry_settingsÚforce_retryÚtry_hotplugÚsleep_totalÚsleepÚsleep_period)rs   r0   rt   Ú
udevactionr/   Úhandler_clsÚevent_handlerÚstartr)   r)   r*   Úhandle_hotplugÏ   s,   
üÿûr‰   c                 C   sÎ   g d¢}t dƒ}t|ƒD ]X\}}t d| |t|ƒ¡ z+t d¡ | ¡  |js0t d¡ | ¡  t d¡ | ¡  t d¡ | 	¡  W  d S  t yd } zt d|¡ t
 |¡ |}W Y d }~qd }~ww |‚)	N)rl   é   é   é
   é   z#Bug while processing hotplug event.z!subsystem=%s update attempt %s/%szRefreshing metadataz$Detecting device in updated metadatazApplying config changezUpdating cachez,Exception while processing hotplug event. %s)Ú	ExceptionÚ	enumeraterf   rg   rh   rF   Úskip_hotplug_detectrA   r9   rB   r~   rƒ   )rt   r‡   r/   Ú
wait_timesÚlast_exceptionÚattemptÚwaitru   r)   r)   r*   r�   ç   s6   ü




€ýr�   c                 C   sÒ   | j dd�}|s
dS t| d }tj| tjg¡ |tƒ ¡v }|s-td|› �tj	d� dS t
 | j¡}|j|d v rGtd|› d	�tj	d� d
S |d  |j¡ t
j| j d¡t |¡ddd� t|d
| jd� d
S )Nrw   rx   Frl   z#hotplug not supported for event of )ÚfileÚscopesz)Not installing hotplug for event of type z. Reason: Already done.Tzhotplug.enabledÚwi   )ÚomodeÚmode)Únetwork_hotplug_enabledrm   )rz   rp   r   rD   r{   ra   ÚsetÚprintÚsysÚstderrr   Úread_hotplug_enabled_fileÚpathsÚvalueÚappendÚ
write_fileÚ	get_cpathÚjsonÚdumpsr   rm   )rs   rt   r/   ro   Úhotplug_supportedÚhotplug_enabled_filer)   r)   r*   Úenable_hotplug  s<   ÿÿ
ý
üÿr©   c              	   C   s˜  t j| tdd�}tg |d�}| ¡  t |j¡ d|jv r&t 	|j 
d¡¡ t d| |j|jd|v r5|jnd d|v r=|jnd ¡ |�w za|jdkrmzt||jƒ}W n tyc   td	ƒ t d
¡ Y nw t|ridndƒ n6|jdkr~t||j|j|jd� n%t ¡ dkr�tj d¡ t d
¡ t||jd�s›t d
¡ td|j› �ƒ W n ty±   t d¡ ‚ w W d   ƒ n1 s¼w   Y  t d¡ t ¡  d S )NT)Úreporting_enabled)Úds_depsÚreporterr   zh%s called with the following arguments: {hotplug_action: %s, subsystem: %s, udevaction: %s, devpath: %s}r…   r0   r   z9Unable to determine hotplug state. No datasource detectedrl   ÚenabledÚdisabledr   )rs   r0   rt   r…   r   z9Root is required. Try prepending your command with sudo.
)rs   rt   z)Enabled cloud-init hotplug for subsystem=z*Received fatal exception handling hotplug!zExiting hotplug handler)r   ÚReportEventStackr"   r   Úread_cfgr   Úsetup_loggingrm   r   Úupdate_configurationra   rf   rg   r   rt   r…   r0   r|   r   rœ   r�   Úexitr‰   rP   Úgetuidrž   Úwriter©   rŽ   Ú	exceptionÚflush_events)ÚnameÚargsÚhotplug_reporterrs   r/   r)   r)   r*   Úhandle_args'  sx   ÿ
ù

ÿÿû
üÿ
ÿ
ÿÿ€
þ€Û
)r»   Ú__main__r-   )r<   N)2r"   rJ   r   r¥   ÚloggingrP   r�   r~   Ú	cloudinitr   r   r   Ú#cloudinit.config.cc_install_hotplugr   Úcloudinit.eventr   r   Úcloudinit.logr   Úcloudinit.netr	   Úcloudinit.net.network_stater
   Úcloudinit.reportingr   Úcloudinit.sourcesr   r   Úcloudinit.stagesr   Ú	getLoggerrG   rf   r!   r+   ÚABCr,   rN   ÚNETWORKrp   rv   Ústrr|   r‰   r�   rM   r©   r»   Ú
parse_argsr¹   r)   r)   r)   r*   Ú<module>   sD   

62
(ÿ
#E
þ