U
    M[^%                     @   s   d dl Z d dlmZ d dlmZmZmZ d dlmZ d dlm	Z	 dZ
ddd	gZzd d
lmZmZmZ W n ek
rz   Y nX dddZG dd dejZdd ZdS )    N)base)apt
exceptionsstatus)util)ApplicationStatusz/usr/bin/snapg      ?g      ?g      @)AnyDictTuplez)Invalid Auth-Token provided to livepatch.z2Your running kernel is not supported by Livepatch.)zUnknown Auth-Tokenzunsupported kernelc                       s   e Zd ZdZdZdZdZddd dffZdd	eed
ddZ	deeedddZ
dddZddddZdddeed fddZ  ZS )LivepatchEntitlementzhttps://ubuntu.com/livepatchZ	livepatchZ	LivepatchzCanonical Livepatch servicez'Cannot install Livepatch on a containerc                   C   s   t  S )N)r   Zis_container r   r   A/usr/lib/python3/dist-packages/uaclient/entitlements/livepatch.py<lambda>"       zLivepatchEntitlement.<lambda>F)silent_if_inapplicable)r   returnc             
   C   sB  | j |dsdS tds4ttstd ttj ztddgtj	 W n4 t
jk
r } ztdt| W 5 d}~X Y nX tjdd	d
dgdtjd tjtdddgdd ndt krt
d| jtd ztjtd	dgdtd W n< tjk
r2 } zdt| }t
|W 5 d}~X Y nX | jdddS )a  Enable specific entitlement.

        :param silent_if_inapplicable:
            Don't emit any messages until after it has been determined that
            this entitlement is applicable to the current machine.

        @return: True on success, False otherwise.
        )silentF/snap/bin/canonical-livepatchzInstalling snapdzapt-getupdatez<Trying to install snapd. Ignoring apt-get update failure: %sNZinstallz--assume-yesZsnapdT)captureZretry_sleepswaitsystemzseed.loadedr   zE/usr/bin/snap is present but snapd is not installed; cannot enable {}z#Installing canonical-livepatch snapcanonical-livepatchz$Unable to install Livepatch client: process_directivesprocess_token)Z
can_enabler   whichSNAP_CMDprintr   ZMESSAGE_APT_UPDATING_LISTSr   Zrun_apt_commandZMESSAGE_APT_UPDATE_FAILEDr   ZUserFacingErrorloggingdebugstrsubpZAPT_RETRIESZget_installed_packagesformattitleSNAP_INSTALL_RETRIESProcessExecutionErrorsetup_livepatch_config)selfr   emsgr   r   r   enable'   sZ    	

 

 
 zLivepatchEntitlement.enableT)r   r   r   c              
   C   s  | j j| j}|rjzt| W nH tjk
rh } z(dt| }t| t	
| W Y dS d}~X Y nX |r|d}|st	d| j | j jd }|  \}}|tjjkrt	d| j ztdd	g W n: tjk
r } zt	
t| W Y dS d}~X Y nX ztjdd
|gdd W n~ tjk
r } z\d}t D ]&\}	}
|	t|krH||
7 } qpqH|dkr|t|7 }t| W Y dS d}~X Y nX td dS )a  Processs configuration setup for livepatch directives.

        :param process_directives: Boolean set True when directives should be
            processsed.
        :param process_token: Boolean set True when token should be
            processsed.
        zUnable to configure Livepatch: FNresourceTokenzHNo specific resourceToken present. Using machine token as %s credentialsZmachineTokenz.Disabling %s prior to re-attach with new tokenr   disabler,   Tr   zUnable to enable Livepatch: zCanonical livepatch enabled.)cfgZentitlementsgetnameprocess_config_directivesr   r'   r"   r   r    errorr!   r%   Zmachine_tokenapplication_statusr   r   DISABLEDinfor#   ERROR_MSG_MAPitems)r)   r   r   Zentitlement_cfgr*   r+   Zlivepatch_tokenr4   Z_detailsZerror_messageZprint_messager   r   r   r(   [   s`    





z+LivepatchEntitlement.setup_livepatch_configc                 C   s\   |  |sdS tdsdS tjddgdd td |sDtd tjtddgdd dS )	zYDisable specific entitlement

        @return: True on success, False otherwise.
        Fr   Tr.   r   z!Removing canonical-livepatch snapremover   )Zcan_disabler   r   r#   r    r!   r   r   )r)   r   r   r   r   r.      s    


zLivepatchEntitlement.disablezTuple[ApplicationStatus, str])r   c              
   C   sd   t jdf}ztddg W nB tjk
r^ } z"tdt| t jt|f}W 5 d }~X Y nX |S )N r   r   zLivepatch not enabled. %s)	r   ZENABLEDr   r#   r'   r    r!   r"   r5   )r)   r   r*   r   r   r   r4      s    
 z'LivepatchEntitlement.application_statuszDict[str, Any])orig_accessdeltasallow_enabler   c                    s   t  |||rdS |  \}}|tjjkr0dS |di }|di }tddg}t|	|}	t|dd}
t
|	|
grtd| j | j|	|
d	S dS )
a1  Process any contract access deltas for this entitlement.

        :param orig_access: Dictionary containing the original
            resourceEntitlement access details.
        :param deltas: Dictionary which contains only the changed access keys
        and values.
        :param allow_enable: Boolean set True if allowed to perform the enable
            operation. When False, a message will be logged to inform the user
            about the recommended enabled service.

        :return: True when delta operations are processed; False when noop.
        Tentitlement
directivescaCertsremoteServerr-   Fz$Updating '%s' on changed directives.r   )superprocess_contract_deltasr4   r   r   r5   r0   setboolintersectionanyr    r6   r1   r(   )r)   r;   r<   r=   r4   _Zdelta_entitlementZdelta_directivesZsupported_deltasr   r   	__class__r   r   rC      s&    z,LivepatchEntitlement.process_contract_deltas)TT)F)F)__name__
__module____qualname__Zhelp_doc_urlr1   r%   ZdescriptionZstatic_affordancesrE   r,   r(   r.   r4   rC   __classcell__r   r   rI   r   r      s4   5    =
 r   c                 C   s   | sdS |  di  di }| d}|rDtjddd|gdd	 | d
d}|drf|dd }|rtjddd|gdd	 dS )a  Process livepatch configuration directives.

    We process caCerts before remoteServer because changing remote-server
    in the canonical-livepatch CLI performs a PUT against the new server name.
    If new caCerts were required for the new remoteServer, this
    canonical-livepatch client PUT could fail on unmatched old caCerts.

    @raises: ProcessExecutionError if unable to configure livepatch.
    Nr>   r?   r@   r   Zconfigzca-certs={}Tr   rA   r:   /zremote-server={})r0   r   r#   r$   endswith)r/   r?   Zca_certsZremote_serverr   r   r   r2      s.    


r2   )r    Zuaclient.entitlementsr   Zuaclientr   r   r   r   Zuaclient.statusr   r   r&   typingr   r	   r
   ImportErrorr7   ZUAEntitlementr   r2   r   r   r   r   <module>   s    
 C