U
    lHJe2                     @   s.  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	m
Z
 d dlmZmZmZmZmZ d dlmZmZmZmZmZmZ d dlmZ d dlmZ dZd	Zd
ZdZe  Z!e"e#e$Z%ej&G dd dej'Z(G dd deZ)G dd deZ*G dd deZ+G dd deZ,e	e+ dddZ-e	e. e	e( dddZ/G dd dej0Z1e	e( dddZ2e.e.e.e.e
e3e	e3 f d d!d"Z4e.e.e.e.e	e j  e	e( d#d$d%Z5edd&e(dd'd(Z6d4e.e	ee7  dd)d*d+Z8d5e	e. e	e. e	ee7  dd,d-d.Z9e.e	e. d/d0d1Z:e3dd2d3Z;dS )6    N)	lru_cache)ListOptionalTuple)event_logger
exceptionsmessagessystemutil)BoolDataValue
DataObjectFieldIncorrectTypeErrorStringDataValue	data_list)state_files)serviceclientz
http-proxyzhttps-proxyz/snap/bin/canonical-livepatchz/v1/api/kernels/supportedc                   @   s*   e Zd Ze Ze Ze Ze Ze ZdS )LivepatchSupportN)	__name__
__module____qualname__object	SUPPORTEDKERNEL_UPGRADE_REQUIRED
KERNEL_EOLUNSUPPORTEDUNKNOWN r   r   4/usr/lib/python3/dist-packages/uaclient/livepatch.pyr       s
   r   c                   @   sD   e Zd ZededddededddgZee ee	 ddd	Z
d
S )LivepatchPatchFixStatusnameFNameZrequiredZdict_keypatchedZPatchedr    r#   c                 C   s   || _ || _d S Nr$   )selfr    r#   r   r   r   __init__/   s    z LivepatchPatchFixStatus.__init__N)r   r   r   r   r   r   fieldsr   strboolr'   r   r   r   r   r   )   s   r   c                   @   s`   e Zd ZededddedeedddededddgZee	 ee
e  ee	 d	d
dZdS )LivepatchPatchStatusstateFStater"   fixesZFixesversionZVersionr,   r.   r/   c                 C   s   || _ || _|| _d S r%   r0   )r&   r,   r.   r/   r   r   r   r'   D   s    zLivepatchPatchStatus.__init__N)r   r   r   r   r   r   r   r(   r   r)   r   r'   r   r   r   r   r+   8   s   
r+   c                   @   sX   e Zd ZededddededddededddgZee ee ee d	d
dZ	dS )LivepatchStatusStatuskernelFZKernelr"   	livepatchZ	Livepatch	supported	Supportedr2   r3   r4   c                 C   s   || _ || _|| _d S r%   r6   )r&   r2   r3   r4   r   r   r   r'   `   s    zLivepatchStatusStatus.__init__N)
r   r   r   r   r   r+   r(   r   r)   r'   r   r   r   r   r1   O   s$   r1   c                   @   s8   e Zd ZedeedddgZeee  dddZ	dS )	LivepatchStatusstatusFZStatusr"   r8   c                 C   s
   || _ d S r%   r9   )r&   r8   r   r   r   r'   u   s    zLivepatchStatus.__init__N)
r   r   r   r   r   r1   r(   r   r   r'   r   r   r   r   r7   k   s   
r7   )returnc               
   C   s  t  std d S zttddddg\} }W n" tjk
rR   td Y d S X zt	
| }W n: t	jk
r } ztjd| |d W Y d S d }~X Y nX zt|}W n" tk
r   td	|  Y d S X |jd kst|jd
k  rtd d S |jd S )Nz$canonical-livepatch is not installedr8   z	--verbosez--formatjsonz7canonical-livepatch returned error when checking statuszPJSONDecodeError while parsing livepatch status, returning None. output was: "%s")exc_infoz<canonical-livepatch status returned unexpected structure: %s   z!canonical-livepatch has no statusr   )is_livepatch_installedLOGdebugr	   subpLIVEPATCH_CMDr   ZProcessExecutionErrorwarningr;   loadsZJSONDecodeErrorr7   Z	from_dictr   r8   len)out_Zstatus_jsoneZstatus_rootr   r   r   r8   |   s>    


r8   )
status_strr:   c                 C   sJ   | dkrt jS | dkrt jS | dkr*t jS | dkr8t jS | dkrFt jS d S )Nr4   zkernel-upgrade-requiredzkernel-end-of-lifeZunsupportedunknown)r   r   r   r   r   r   )rI   r   r   r   (_convert_str_to_livepatch_support_status   s    rK   c                   @   s2   e Zd ZdZeeeeeej ee dddZdS )UALivepatchClientZlivepatch_urlr/   flavorarchcodename
build_dater:   c              
   C   s   |||||d k	r|  ndd}|  }z| jt||d}W n< tk
rx }	 ztd t|	 W Y d S d }	~	X Y nX |jdkrtd t|j d S |j	
d}
|
d kst|
tr|
rtjS tjS t|
S )NrJ   )zkernel-versionZflavourZarchitecturerP   z
build-date)query_paramsheadersz4error while checking livepatch supported kernels API   z0livepatch supported kernels API was unsuccessfulr5   )Z	isoformatrS   Zrequest_url"LIVEPATCH_API_V1_KERNELS_SUPPORTED	Exceptionr?   rC   codeZbodyZ	json_dictget
isinstancer*   r   r   r   rK   )r&   r/   rN   rO   rP   rQ   rR   rS   ZresponserH   Zapi_supported_valr   r   r   is_kernel_supported   s:    	
	




z%UALivepatchClient.is_kernel_supportedN)	r   r   r   Zcfg_url_base_attrr)   r   datetimer   rZ   r   r   r   r   rL      s   rL   c                  C   s   t  } | d krd S t| jS r%   )r8   rK   r4   )Z	lp_statusr   r   r   _on_supported_kernel_cli   s    r\   )r/   rN   rO   rP   r:   c                 C   s   zt j }W n tk
r&   d}Y nX |dk	rtjtjjtjdd }t	|j
|k|j| k|j|k|j|k|j|kgr|jdkrtd d|jfS dS )zOCheck local cache of kernel support

    :return: (is_cache_valid, result)
    N   )Zdaysz-livepatch kernel support cache has None valueT)FN)r   livepatch_support_cachereadrV   r[   nowtimezoneutcZ	timedeltaall	cached_atr/   rN   rO   rP   r4   r?   rC   )r/   rN   rO   rP   Z
cache_dataZone_week_agor   r   r   _on_supported_kernel_cache   s,    

	


re   rM   c                 C   sx   t  j| ||||d}d }|tjkr*d}n|tjkr8d}tjtj| ||||t	j	
t	jjd |d krttd |S )N)r/   rN   rO   rP   rQ   TF)r/   rN   rO   rP   r4   rd   z3livepatch kernel support API response was ambiguous)rL   rZ   r   r   r   r   r^   writeZLivepatchSupportCacheDatar[   r`   ra   rb   r?   rC   )r/   rN   rO   rP   rQ   r4   Zcache_supportedr   r   r   _on_supported_kernel_api	  s2    	


rg   )maxsizec                  C   s   t  } | dk	rtd | S t }|jdksB|jdksB|jdkrRtd t	j
S t|j}t j}dj|j|jd}t||j||\}}|rtd |dkrt	j
S |rt	jS |st	jS td t||j|||j}|dkrt	j
S |S )z
    Checks CLI, local cache, and API in that order for kernel support
    If all checks fail to return an authoritative answer, we return None
    Nzusing livepatch cli for supportzHunable to determine enough kernel information to check livepatch supportz{major}.{minor})majorminorzusing livepatch support cachezusing livepatch support api)r\   r?   r@   r	   Zget_kernel_inforN   ri   rj   rC   r   r   r
   Zstandardize_arch_nameZuname_machine_archZget_release_infoZseriesformatre   r   r   rg   rQ   )Zcli_saysZkernel_inforO   rP   Zlp_api_kernel_verZis_cache_validZ
cache_saysZapi_saysr   r   r   on_supported_kernel.  s\    

    

rl   )protocol_typeretry_sleepsr:   c                 C   s(   t  s
dS tjtdd| g|d dS )a  
    Unset livepatch configuration settings for http and https proxies.

    :param protocol_type: String either http or https
    :param retry_sleeps: Optional list of sleep lengths to apply between
        retries. Specifying a list of [0.5, 1] tells subp to retry twice
        on failure; sleeping half a second before the first retry and 1 second
        before the second retry.
    Nconfigz	{}-proxy=rn   )r>   r	   rA   rB   rk   )rm   rn   r   r   r   unconfigure_livepatch_proxyj  s    rq   )
http_proxyhttps_proxyrn   r:   c                 C   sj   ddl m} | s|r*ttjj|jd | rHtj	t
dd| g|d |rftj	t
dd|g|d dS )	a  
    Configure livepatch to use http and https proxies.

    :param http_proxy: http proxy to be used by livepatch. If None, it will
                       not be configured
    :param https_proxy: https proxy to be used by livepatch. If None, it will
                        not be configured
    :@param retry_sleeps: Optional list of sleep lengths to apply between
                               snap calls
    r   )LivepatchEntitlement)servicero   zhttp-proxy={}rp   zhttps-proxy={}N)Zuaclient.entitlementsrt   eventinfor   ZSETTING_SERVICE_PROXYrk   titler	   rA   rB   )rr   rs   rn   rt   r   r   r   configure_livepatch_proxy~  s"    ry   )keyr:   c                 C   s\   t tdg\}}td| |tj}|r6|dnd}|rLtdd|}|rX|	 S dS )z
    Gets the config value from livepatch.
    :param key: can be any valid livepatch config option
    :return: the value of the livepatch config option, or None if not set
    ro   z
^{}: (.*)$r=   Nz\"(.*)\"z\g<1>)
r	   rA   rB   researchrk   	MULTILINEgroupsubstrip)rz   rF   rG   matchvaluer   r   r   get_config_option_value  s    r   c                   C   s   t td k	S r%   )r	   ZwhichrB   r   r   r   r   r>     s    r>   )N)NNN)<r[   enumr;   Zloggingr{   	functoolsr   typingr   r   r   Zuaclientr   r   r   r	   r
   Zuaclient.data_typesr   r   r   r   r   r   Zuaclient.filesr   Zuaclient.httpr   ZHTTP_PROXY_OPTIONZHTTPS_PROXY_OPTIONrB   rU   Zget_event_loggerrv   Z	getLoggerZreplace_top_level_logger_namer   r?   uniqueEnumr   r   r+   r1   r7   r8   r)   rK   ZUAServiceClientrL   r\   r*   re   rg   rl   floatrq   ry   r   r>   r   r   r   r   <module>   sx    )/    %<  
   
%