o
    ÙKÕir  ã                   @   s:  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 d dl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mZ d dlmZ d dlmZmZ d d	lmZmZ d d
l m!Z!m"Z" d dl#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z) d dl*m+Z+m,Z,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2 e 3¡ Z4e 5e 6e7¡¡Z8dZ9dZ:dZ;e)j<j=e2j>ej? e2j@ e)jAj=e2jBejC e2j@ e)jDj=e2jEejF e2j@ e)jGj=e2jEejH e2j@ e)jIj=e2jJejK e2j@ e&jLj=e2j>ejM e2j@ e&jNj=e2jEejO e2j@ e9e2j>ejP e2j@ e:e2j>ejQ e2j@ e;e2j>ejR e2j@ i
ZSdZTdZUdjVejWejXejYejZd�Z[dZ\dZ]i dd“dd“de ^¡ “dd“dd “d!d“d"d“d#d“d$g “d%e(jAj=“d&ej_“d'i “d(g “d)d*d*d*g e)jDj=d+œ“d,d*d*d*g d-œ“d.d “Z`d/d0„ Zad1eebef fd2d3„Zcd4ed1eebef fd5d6„Zdd4ed1eebef fd7d8„Zed1eebef fd9d:„ZfdUd4ed;egd1eebef fd<d=„Zhd>eeebef  d?ebd1eebef fd@dA„Zi	 dUdBebd;egd1eeebef ejf fdCdD„ZkdEebd1ebfdFdG„ZldHeeeb  d1ebfdIdJ„Zm	dVdKeeebebf  dLeeb d1eeb fdMdN„Znd"ee d1ebfdOdP„ZodUd=eebef d;egd1ebfdQdR„ZpdSdT„ ZqdS )Wé    N)ÚOrderedDict)ÚdatetimeÚtimezone)ÚEnum)ÚAnyÚDictÚListÚOptionalÚTuple)Úevent_loggerÚ
exceptionsÚ	livepatchÚlockÚmessagesÚutilÚversion)Ú_is_attached)ÚUA_CONFIGURABLE_KEYSÚUAConfig)Úget_available_resourcesÚget_contract_information)ÚATTACH_FAIL_DATE_FORMATÚPRINT_WRAP_WIDTH)Úentitlement_factory)ÚContractStatusÚUserFacingAvailabilityÚUserFacingConfigStatusÚUserFacingStatus)Úmachine_tokenÚnoticesÚstate_filesÚuser_config_file)ÚNotice)ÚTxtColorÚ	essentialÚstandardÚadvancedz({name: <17}{available: <11}{description}zJ{name: <17}{available: <11}{entitled: <11}{auto_enabled: <16}{description}z4{name: <17}{entitled: <10}{status: <13}{description}©ÚnameÚentitledÚstatusÚdescriptionz4{name: <17}{entitled: <19}{status: <22}{description}z={marker} {name: <15}{entitled: <19}{status: <22}{description}Ú_doczUContent provided in json response is currently considered Experimental and may changeÚ_schema_versionz0.1r   Ú
machine_idÚattachedFÚ	effectiveÚexpiresÚoriginÚservicesÚexecution_statusÚexecution_detailsÚfeaturesr   ÚcontractÚ ©Úidr(   Ú
created_atÚproductsÚtech_support_levelÚaccount©r(   r:   r;   Úexternal_account_idsÚ	simulatedc                 C   s   dd„ |   ¡ D ƒS )Nc                 S   s4   g | ]}|j js|j jn|j j|jj|jjd œ‘qS ))r(   Úreason_codeÚreason)ÚentitlementÚ
is_variantr(   Úvariant_nameÚ	named_msgÚmsg©Ú.0Úservice© rL   ú1/usr/lib/python3/dist-packages/uaclient/status.pyÚ
<listcomp>Ž   s    
ú
ÿùÿz,_get_blocked_by_services.<locals>.<listcomp>)Úblocking_incompatible_services)ÚentrL   rL   rM   Ú_get_blocked_by_services�   s   
örQ   Úreturnc              
      sô   d }d}|   ¡ }|  ¡ }| jˆv rdnd}i }|tjkr tj}	n=| jˆv r.tj}	ˆ| j }n/|  ¡ \}	}
|	tj	krA|
j|
j
dœ}n|
rF|
j
}|	tjkrMd}| jr]‡ ‡fdd„| j ¡ D ƒ}t| ƒ}| j| j|j|	j|||||dœ	}| jsx||d< |S )	Nr8   ÚnoÚyes)ÚcodeÚmessagec                    s$   i | ]\}}|t |ˆ d �ˆˆ ƒ“qS ))Úcfg)Ú_attached_service_status)rJ   rF   Úvariant_cls©rW   Úinapplicable_resourcesrL   rM   Ú
<dictcomp>º   s    ûýÿz,_attached_service_status.<locals>.<dictcomp>)	r(   r+   r)   r*   Ústatus_detailsÚdescription_overrideÚ	availableÚ
blocked_byÚwarningÚvariants)Ústatus_description_overrideÚcontract_statusr(   r   Ú
UNENTITLEDr   ÚUNAVAILABLEÚINAPPLICABLEÚuser_facing_statusÚWARNINGrH   rb   ÚitemsrQ   Úpresentation_namer+   ÚvaluerE   )rP   r[   rW   ra   r]   r^   rd   r_   rb   Ú
ent_statusÚdetailsr`   Úservice_statusrL   rZ   rM   rX   œ   sL   


þ
ú	÷rX   rW   c                 C   sÒ  t  tj¡ t  tj¡ t| ƒjrt  tj¡ t 	t
¡}t | ¡}|jd }|d }tjj}| |d d| d¡t  ¡ p=g |d |d | dd	¡| d
g ¡|dœ|jd |jd |j dd	¡|j dg ¡dœdœ¡ | d¡rt|j|d< | d¡r|d |d< |j d¡}|s‹t| ƒ}dd„ t|dd„ d�D ƒ}|D ]$}zt| | dd	¡d�}	W n
 tjy²   Y qšw |d  t|	|| ƒ¡ qš|d jdd„ d� | ¡  di ¡ d¡}
|
rç|
 di ¡ d¡}|rç||d  d!< |S )"z8Return configuration of attached status as a dictionary.ÚmachineTokenInfoÚcontractInfoÚ	machineIdTr2   r:   r(   Ú	createdAtr8   r<   r9   ÚexternalAccountIDsr?   )r.   r/   r2   r   r7   r>   ÚeffectiveTor1   ÚeffectiveFromr0   ÚavailableResourcesc                 S   s&   i | ]}|  d ¡s|d |  d¡“qS )r_   r(   r+   ©Úget©rJ   ÚresourcerL   rL   rM   r\     s    ýÿz$_attached_status.<locals>.<dictcomp>c                 S   ó   |   dd¡S ©Nr(   r8   rx   ©ÚxrL   rL   rM   Ú<lambda>  ó    z"_attached_status.<locals>.<lambda>©Úkey©rW   r(   r3   c                 S   r|   r}   rx   r~   rL   rL   rM   r€     r�   ÚsupportrD   ÚaffordancesÚsupportLevelr7   r=   )r   Úremover"   ÚAUTO_ATTACH_RETRY_FULL_NOTICEÚAUTO_ATTACH_RETRY_TOTAL_FAILUREr   Úis_attached_and_contract_validÚCONTRACT_EXPIREDÚcopyÚdeepcopyÚDEFAULT_STATUSr   Úget_machine_token_filer   rg   rl   Úupdatery   Úlistr>   Úcontract_expiry_datetimer   Úsortedr   r   ÚEntitlementNotFoundErrorÚappendrX   ÚsortÚentitlements)rW   ÚresponseÚmachine_token_filerp   rq   r=   Ú	resourcesr[   r{   rP   r…   r‡   rL   rL   rM   Ú_attached_status×   sp   






ûÿüôÿ


þÿ
ÿÿrœ   c                 C   sà   t  t¡}t| ƒ}|D ]X}| d¡rtjj}ntjj}zt	| | dd¡d�}W n t
jy;   t d| dd¡¡ Y qw |jdkrNt ¡ tjjkrN| ¡ }nd}|d	  | d
|d ¡|j||dœ¡ q|d	 jdd„ d� |S )z#Return unattached status as a dict.r_   r(   r8   r„   z@Ignoring availability of unknown service %s from contract serverzwithout a 'name' keyr   Nr3   ÚpresentedAs)r(   r+   r^   r_   c                 S   r|   r}   rx   r~   rL   rL   rM   r€   G  r�   z$_unattached_status.<locals>.<lambda>r‚   )r�   rŽ   r�   r   ry   r   Ú	AVAILABLErl   rf   r   r   r•   ÚLOGÚdebugr(   r   Úon_supported_kernelÚLivepatchSupportÚUNSUPPORTEDrc   r–   r+   r—   )rW   r™   r›   r{   r_   rP   Údescr_overriderL   rL   rM   Ú_unattached_status  s<   



ýú
ÿ
üÿr¥   c                 C   sä   t }|jj}tj}t ¡ \}}t ¡ pg }|dkr&|j	j}tj
j||d�}ntjjr7|jj}d}tjj|d�}|||| j| j| jdœ}tjj ¡ }	tD ]}
t| |
ƒri|	|
 du rit| |
ƒ}t|tƒre|j}||	|
< qK|	|d d< |S )	aG  Return a dict with execution_status, execution_details and notices.

    Values for execution_status will be one of UserFacingConfigStatus
    enum:
        inactive, active, reboot-required
    execution_details will provide more details about that state.
    notices is a list of tuples with label and description items.
    r   )ÚpidÚlock_holderzconfiguration changes)Ú	operation)r4   r5   r   Úconfig_pathÚconfigr6   Nrª   Ú	ua_config)r   ÚINACTIVErl   r   ÚNO_ACTIVE_OPERATIONSr   Úcheck_lock_infor   r’   ÚACTIVEÚ	LOCK_HELDÚformatr    Úreboot_cmd_marker_fileÚ
is_presentÚREBOOTREQUIREDÚENABLE_REBOOT_REQUIRED_TMPLÚcfg_pathrW   r6   r!   Úuser_configÚpublic_configÚto_dictr   ÚhasattrÚgetattrÚ
isinstancer   )rW   Ú
userStatusÚ
status_valÚstatus_descÚlock_pidr§   Únotices_listr¨   Úretr«   rƒ   ÚvalrL   rL   rM   Ú_get_config_statusL  sB   	ÿÿú	

€rÄ   Úshow_allc                 C   sd   t | ƒjr
t| ƒ}nt| ƒ}| t| ƒ¡ t ¡ rtj	 
|¡ |s0dd„ | dg ¡D ƒ}||d< |S )a  Return status as a dict, using a cache for non-root users

    When unattached, get available resources from the contract service
    to report detailed availability of different resources for this
    machine.

    Write the status-cache when called by root.
    c                 S   ó    g | ]}|  d d¡dkr|‘qS ©r_   rT   rx   rI   rL   rL   rM   rN   �  ó
    þzstatus.<locals>.<listcomp>r3   )r   Úis_attachedrœ   r¥   r‘   rÄ   r   Úwe_are_currently_rootr    Ústatus_cache_fileÚwritery   )rW   rÅ   r™   Úavailable_servicesrL   rL   rM   r*   {  s   
	

þr*   r˜   Úentitlement_namec                 C   s`   | D ]'}|  d¡|kr)|  d¡rdnd|  di ¡  d¡rdnd|  di ¡dœ  S qddi dœS )	z0Extract information from the entitlements array.Útyper)   rT   rS   ÚobligationsÚenableByDefaultr†   )r)   Úauto_enabledr†   rx   )r˜   rÎ   rD   rL   rL   rM   Ú_get_entitlement_information™  s   ÿÿ

÷ÿrÓ   Útokenc              
   C   s  d}t  t¡}zt| |ƒ}W n tjy+ } zt|dƒr%|jdkr%t ¡ ‚|‚d}~ww | 	di ¡}| 	di ¡}| 
| 	dd¡| 	d	d¡| 	d
d¡| 	dg ¡dœ| 	d	d¡| 	d¡| 	d
d¡| 	dg ¡dœddœ¡ t tj¡}	| 	d¡r±| 	d¡|d< |d }
|
|	 }| ¡ dkr±tjj|d d |
 t¡d�}tj|j|jd� t tjd |j d ¡ d}| 	d¡rò| 	d¡|d< |d }|	| }| ¡ dkròtjj|d d | t¡d�}tj|j|jd� t tjd |j d ¡ d}t| ƒ}dd„ t|dd„ d�D ƒ}| 	dg ¡}|D ]B}| 	d	d¡}zt| |d �}W n tj�y'   Y �qw t ||ƒ}|d!  !| 	d"|j¡|j"|d# |d$ |j|v�rGd%nd&d'œ¡ �q|d! j#d(d„ d� t |d)ƒ}|d# �rr|d*  	d+¡}|�rr||d d,< | 
t$| ƒ¡ |�s‹d-d„ | 	d!g ¡D ƒ}||d!< ||fS ).z–Get a status dictionary based on a token.

    Returns a tuple with the status dictionary and an integer value - 0 for
    success, 1 for failure
    r   rU   i‘  Nrq   ÚaccountInfor:   r8   r(   rs   r<   )r:   r(   r;   r<   rt   r?   T)r7   r>   rA   ru   r1   r7   )Úcontract_idÚdate)Ú	error_msgÚ
error_codeÚ
é   rv   r0   c                 S   s   g | ]
}|d  s|d ‘qS )r_   r(   rL   rz   rL   rL   rM   rN   õ  s    ýÿz#simulate_status.<locals>.<listcomp>c                 S   s   | d S )Nr(   rL   r~   rL   rL   rM   r€   ÷  s    z!simulate_status.<locals>.<lambda>r‚   ÚresourceEntitlementsr„   r3   r�   r)   rÒ   rT   rS   )r(   r+   r)   rÒ   r_   c                 S   r|   r}   rx   r~   rL   rL   rM   r€     r�   r…   r†   r‡   r=   c                 S   rÆ   rÇ   rx   rI   rL   rL   rM   rN     rÈ   )%r�   rŽ   r�   r   r   ÚContractAPIErrorrº   rU   ÚAttachInvalidTokenErrorry   r‘   r   Únowr   ÚutcÚtotal_secondsr   ÚE_ATTACH_FORBIDDEN_EXPIREDr±   Ústrftimer   ÚeventÚerrorrH   r(   ÚinfoÚSTATUS_TOKEN_NOT_VALIDÚE_ATTACH_FORBIDDEN_NOT_YETr   r”   r   r•   rÓ   r–   r+   r—   rÄ   )rW   rÔ   rÅ   rÂ   r™   Úcontract_informationÚeÚcontract_infoÚaccount_inforß   Úexpiration_datetimeÚdeltarV   Úeffective_datetimer›   r[   r˜   r{   rÎ   rP   Úentitlement_informationr…   r‡   rÍ   rL   rL   rM   Úsimulate_status­  sº   
€ý



ü

ÿüñÿ

þÿ

þÿþÿÿúÿ


þrñ   Ústringc                 C   s   t j ¡ rt | | ¡S | S )z=Return colorized string if using a tty, else original string.)ÚsysÚstdoutÚisattyÚSTATUS_HUMANIZE_COLORIZEry   )rò   rL   rL   rM   Úfor_human_colorized%  s
   ÿÿýr÷   Úcommandsc                 C   st   d}| D ]}|r|d7 }|d  |¡7 }qd  tj|td dd�¡}d|v r*d	}d
}nd}d}djtj|||tjd�S )Nr8   z && ú z \
é   z  )ÚwidthÚsubsequent_indentrÚ   z{
  z
}z{ z }z%{color}{prefix}{content}{suffix}{end})ÚcolorÚprefixÚcontentÚsuffixÚend)ÚjoinÚtextwrapÚwrapr   r±   r#   ÚDISABLEGREYÚENDC)rø   rÿ   ÚcmdÚwrapped_contentrþ   r   rL   rL   rM   Úcolorize_commands.  s,   
ÿÿûr	  Úcolumn_dataÚheaderc                    sj   g }|r	|  |¡ tdd„ | D ƒƒ}|dkr)d |¡‰ | ‡ fdd„| D ƒ¡ |S | dd„ | D ƒ¡ |S )zžReturn a list of content lines to print to console for a section

    Content lines will be center-aligned based on max value length of first
    column.
    c                 S   s   g | ]}t |d  ƒ‘qS )r   )Úlen©rJ   ÚpairrL   rL   rM   rN   U  s    z.get_section_column_content.<locals>.<listcomp>r   z{{:>{}}}: {{}}c                    s   g | ]}ˆ j |Ž ‘qS rL   )r±   r  ©ÚtemplaterL   rM   rN   X  s    c                 S   s   g | ]}|d  ‘qS )rÛ   rL   r  rL   rL   rM   rN   [  s    )r–   Úmaxr±   Úextend)r
  r  rÿ   Útemplate_lengthrL   r  rM   Úget_section_column_contentJ  s   

ÿr  c                 C   s8   | d u rt jS z|  ¡ } W n	 ty   Y nw |  d¡S )Nz%c %Z)r   ÚSTATUS_CONTRACT_EXPIRES_UNKNOWNÚ
astimezoneÚ	Exceptionrã   )r1   rL   rL   rM   Úformat_expires_  s   ÿ
r  c                 C   s4  |   d¡sæ|   d¡r<|   dd¡stjS tjtjtjtjtjtj	d�g}|   dg ¡D ]}| 
tjd)i |¤Ž¡ q)d |¡S |   dd¡sGtjg}n@tjtjtjtj	d�g}|   dg ¡D ]-}|  d¡}|rd|n|  d	d
¡}|  d¡dkrttjntj}| 
tj|  dd
¡||d�¡ qY|   d¡}|r™| 
tj¡ | |¡ |   d¡r¾| 
dtj ¡ t|   di ¡ ¡ ƒD ]\}}	| 
d ||	¡¡ q°|sÈ| d
tjg¡ | d
tjjg¡ t ¡ tjjkrá| d
tjg¡ d |¡S g }
d}|   dd¡sõtjg}n²tg}|   dg ¡D ]¨}|  dd
¡}|  d¡}|�r|n|  d	d
¡}|  dd
¡t|ƒt|  dd
¡ƒ|dœ}|  dd¡}|du�rD|  dd¡}|du�rD|
 
|¡ |  d¡}|�rZ|�sZd}d |d ¡|d< | 
tjd)i |¤Ž¡ |�r¦|�r¦t| ¡ ƒD ]4\}\}}|t |ƒd k�r‚dnd}| 
t!j||  d¡t|  dd
¡ƒt|  dd
¡ƒ|  d	d
¡d�¡ �qqqþ|�rµ| 
d
¡ | 
tj"¡ |   d¡�sÂt |
ƒdk�ræ| 
d
¡ | 
tj¡ |   d¡}|�rÚ| |¡ t |
ƒdk�ræ| |
¡ |   d¡�r| 
dtj ¡ t|   di ¡ ¡ ƒD ]\}}	| 
d ||	¡¡ �qþ| 
d
¡ |�s%|�r| 
tj#¡ n| 
tj¡ | 
tj$jdd �¡ g }|   d!i ¡  dd"¡}|�rF| 
tj%|f¡ |   d#i ¡  dd"¡}|�r[| 
tj&|f¡ |   d$d¡d%k�r…| 
tj't(|   d&¡ƒf¡ |   d#i ¡  d'd"¡}| 
tj)t|ƒf¡ |�r•| 
d
¡ | t*|d(�¡ d |¡S )*z&Format status dict for tabular output.r/   rA   r3   N)r(   r_   r)   rÒ   r+   rÚ   )r(   r_   r+   r^   r+   r8   r_   rT   r(   r   r6   z{}: {}Fr)   r*   r'   ra   rV   rb   Tz{}*rÛ   u   â”œu   â””)Úmarkerr(   r)   r*   r+   r   zpro enable <service>)Úcommandr>   Úunknownr7   r2   Úfreer1   r=   )r
  rL   )+ry   r   ÚSTATUS_NO_SERVICES_AVAILABLEÚSTATUS_SIMULATED_TMPLr±   ÚSTATUS_SERVICEÚSTATUS_AVAILABLEÚSTATUS_ENTITLEDÚSTATUS_AUTO_ENABLEDÚSTATUS_DESCRIPTIONr–   r  ÚSTATUS_UNATTACHED_TMPLÚSTANDALONE_YESÚSTANDALONE_NOÚSTATUS_NOTICESr  ÚSTATUS_FEATURESr”   rj   ÚSTATUS_ALL_HINTÚE_UNATTACHEDrH   r   r¡   r¢   r£   Ú)LIVEPATCH_KERNEL_NOT_SUPPORTED_UNATTACHEDÚSTATUS_HEADERr÷   ÚSTATUS_TMPLÚ	enumerater  ÚVARIANT_STATUS_TMPLÚSTATUS_SERVICE_HAS_VARIANTSÚSTATUS_ALL_HINT_WITH_VARIANTSÚ"STATUS_FOOTER_ENABLE_SERVICES_WITHÚSTATUS_FOOTER_ACCOUNTÚSTATUS_FOOTER_SUBSCRIPTIONÚSTATUS_FOOTER_VALID_UNTILr  ÚSTATUS_FOOTER_SUPPORT_LEVELr  )r*   rÅ   rÿ   rK   r¤   r+   r_   r   rƒ   rl   Úservice_warningsÚhas_variantsro   r)   Úfmt_argsra   Úwarning_messagerb   ÚidxÚ_Úvariantr  ÚpairsÚaccount_nameÚcontract_namer=   rL   rL   rM   Úformat_tabulari  s4  

ûÿ	

ýÿ
ÿ
ýÿý
ýÿ


ÿÿ


ÿ
ý

ÿú




ÿ
ÿ
÷ÿ€





ÿÿþÿÿþÿ

rA  c           
   	   C   sè   t | ƒ}d}tƒ }||d< |D ](}|d |ks| d¡|kr7z
t| |d d�}W n
 tjy2   Y qw |} nq|du rBtj|d�‚t| ƒjr\t	|i | ƒ}|d }|d |d< ||d< n|d ret
jj}	nt
jj}	|	|d< |j|d	< |S )
z¼Return help information from an uaclient service as a dict

    :param name: Name of the service for which to return help data.

    :raises: UbuntuProError when no help is available.
    Nr(   r�   r„   )r(   r*   r)   r_   Úhelp)r   r   ry   r   r   r•   ÚNoHelpContentr   rÉ   rX   r   rž   rl   rf   Ú	help_info)
rW   r(   r›   Úhelp_resourceÚresponse_dictr{   Úhelp_entro   Ú
status_msgr_   rL   rL   rM   rB  %  s6   ÿú



rB  )F)N)rr�   Úloggingró   r  Úcollectionsr   r   r   Úenumr   Útypingr   r   r   r	   r
   Úuaclientr   r   r   r   r   r   r   Ú(uaclient.api.u.pro.status.is_attached.v1r   Úuaclient.configr   r   Úuaclient.contractr   r   Úuaclient.defaultsr   r   Úuaclient.entitlementsr   Ú(uaclient.entitlements.entitlement_statusr   r   r   r   Úuaclient.filesr   r   r    r!   Úuaclient.files.noticesr"   Úuaclient.messagesr#   Úget_event_loggerrä   Ú	getLoggerÚreplace_top_level_logger_nameÚ__name__rŸ   Ú	ESSENTIALÚSTANDARDÚADVANCEDr¯   rl   ÚOKGREENÚSTATUS_STATUS_ENABLEDr  r¬   ÚFAILÚSTATUS_STATUS_DISABLEDrg   r  ÚSTATUS_STATUS_INAPPLICABLErf   ÚSTATUS_STATUS_UNAVAILABLEri   ÚWARNINGYELLOWÚSTATUS_STATUS_WARNINGÚENTITLEDÚSTATUS_ENTITLED_ENTITLEDre   ÚSTATUS_ENTITLED_UNENTITLEDÚSTATUS_SUPPORT_ESSENTIALÚSTATUS_SUPPORT_STANDARDÚSTATUS_SUPPORT_ADVANCEDrö   r$  r  r±   r  r!  ÚSTATUS_STATUSr#  r,  r-  r/  Úget_versionr­   r�   rQ   ÚstrrX   rœ   r¥   rÄ   Úboolr*   rÓ   Úintrñ   r÷   r	  r  r  rA  rB  rL   rL   rL   rM   Ú<module>   s:   $	ÿþÿþÿþÿþÿþÿþÞ(ü
ÿÿýüûúùø	÷
öõôóòûñüêä 

þ;G. /ÿÿ

þÿÿÿ
þx	ÿÿÿ
þ 
 =