U
    Jh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]dde^ dddddg e(jAj=ej_i g dddg e)jDj=ddddg dddZ`d d! Zaeebef d"d#d$Zceeebef d%d&d'Zdeeebef d%d(d)Zeeebef d"d*d+ZfdFeegeebef d,d-d.Zheeebef  ebeebef d/d0d1ZidGebegeeebef ejf d2d3d4Zkebebd5d6d7Zleeeb  ebd8d9d:ZmdHeeebebf  eeb eeb d;d<d=Znee ebd>d?d@ZodIeebef egebdAdBdCZpdDdE ZqdS )J    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)TxtColorZ	essentialZstandardZ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}zUContent provided in json response is currently considered Experimental and may changez0.1F idr%   
created_atproductstech_support_levelr%   r+   r,   Zexternal_account_ids)Z_docZ_schema_versionr   
machine_idattached	effectiveexpiresoriginservicesexecution_statusexecution_detailsfeaturesr   contractaccount	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%   Zreason_codereason)entitlement
is_variantr%   variant_nameZ	named_msgmsg.0service rD   1/usr/lib/python3/dist-packages/uaclient/status.py
<listcomp>   s   

z,_get_blocked_by_services.<locals>.<listcomp>)Zblocking_incompatible_services)entrD   rD   rE   _get_blocked_by_services   s    
rH   )returnc              
      s   d }d}|   }|  }| jkr&dnd}i }|tjkr@tj}	nz| jkr\tj}	| j }n^|  \}	}
|	tj	kr|
j|
j
d}n
|
r|
j
}|	tjkrd}| jr fdd| j D }t| }| j| j|j|	j|||||d	}| js||d< |S )	Nr)   noyes)codemessagec                    s$   i | ]\}}|t | d  qS ))cfg)_attached_service_status)rB   r?   Zvariant_clsrN   inapplicable_resourcesrD   rE   
<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INAPPLICABLEZuser_facing_statusWARNINGr@   rX   itemsrH   Zpresentation_namer(   valuer>   )rG   rQ   rN   rW   rS   rT   rZ   rU   rX   Z
ent_statusZdetailsrV   service_statusrD   rP   rE   rO      sL    



	rO   )rN   rI   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  pzg |d |d |dd	|d
g |d|jd |jd |jdd	|jdg dd |dr|j|d< |dr|d |d< |jd}|st| }dd t|dd dD }|D ]T}zt| |dd	d}	W n tjk
rp   Y q6Y nX |d t|	||  q6|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contractInfoZ	machineIdTr4   r+   r%   	createdAtr)   r-   r*   externalAccountIDsr/   )r0   r1   r4   r   r9   r:   effectiveTor3   effectiveFromr2   ZavailableResourcesc                 S   s&   i | ]}| d s|d | dqS )rU   r%   r(   getrB   resourcerD   rD   rE   rR     s   
 z$_attached_status.<locals>.<dictcomp>c                 S   s   |  ddS Nr%   r)   rh   xrD   rD   rE   <lambda>      z"_attached_status.<locals>.<lambda>keyrN   r%   r5   c                 S   s   |  ddS rl   rh   rm   rD   rD   rE   ro     rp   supportr=   affordancessupportLevelr9   r.   )r   remover"   ZAUTO_ATTACH_RETRY_FULL_NOTICEZAUTO_ATTACH_RETRY_TOTAL_FAILUREr   Zis_attached_and_contract_validZCONTRACT_EXPIREDcopydeepcopyDEFAULT_STATUSr   Zget_machine_token_filer   r]   r`   updateri   listr:   Zcontract_expiry_datetimer   sortedr   r   EntitlementNotFoundErrorappendrO   sortentitlements)rN   responseZmachine_token_filerb   rc   r.   	resourcesrQ   rk   rG   rt   rv   rD   rD   rE   _attached_status   sp    






 



r   c                 C   s   t t}t| }|D ]}|dr.tjj}ntjj}zt	| |ddd}W n. t
jk
r|   td|dd Y qY nX |jdkrt tjjkr| }nd}|d	 |d
|d |j||d q|d	 jdd d |S )z#Return unattached status as a dict.rU   r%   r)   rs   z@Ignoring availability of unknown service %s from contract serverzwithout a 'name' keyr   Nr5   presentedAs)r%   r(   rT   rU   c                 S   s   |  ddS rl   rh   rm   rD   rD   rE   ro   G  rp   z$_unattached_status.<locals>.<lambda>rq   )rx   ry   rz   r   ri   r   	AVAILABLEr`   r\   r   r   r~   LOGdebugr%   r   on_supported_kernelLivepatchSupportUNSUPPORTEDrY   r   r(   r   )rN   r   r   rk   rU   rG   descr_overriderD   rD   rE   _unattached_status  s>    





r   c                 C   s   t }|jj}tj}t \}}t p(g }|dkrL|j	j}tj
j||d}n"tjjrn|jj}d}tjj|d}|||| j| j| jd}tjj }	tD ]<}
t| |
r|	|
 dkrt| |
}t|tr|j}||	|
< q|	|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)r6   r7   r   Zconfig_pathconfigr8   Nr   	ua_config)r   INACTIVEr`   r   NO_ACTIVE_OPERATIONSr   Zcheck_lock_infor   r|   ACTIVEZ	LOCK_HELDformatr    Zreboot_cmd_marker_fileZ
is_presentZREBOOTREQUIREDZENABLE_REBOOT_REQUIRED_TMPLZcfg_pathrN   r8   r!   Zuser_configZpublic_configZto_dictr   hasattrgetattr
isinstancer   )rN   Z
userStatusZ
status_valZstatus_descZlock_pidr   Znotices_listr   retr   rr   valrD   rD   rE   _get_config_statusL  sB    	 	


r   )rN   show_allrI   c                 C   sd   t | jrt| }nt| }|t|  t r>tj	
| |s`d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   s    g | ]}| d ddkr|qS rU   rK   rh   rA   rD   rD   rE   rF     s   zstatus.<locals>.<listcomp>r5   )r   is_attachedr   r   r{   r   r   Zwe_are_currently_rootr    Zstatus_cache_filewriteri   )rN   r   r   available_servicesrD   rD   rE   r'   {  s    	


r'   )r   entitlement_namerI   c                 C   s`   | D ]N}| 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&   rK   rJ   ZobligationsZenableByDefaultru   )r&   auto_enabledru   rh   )r   r   r=   rD   rD   rE   _get_entitlement_information  s    
r   )tokenr   rI   c              
   C   s6  d}t t}zt| |}W nD tjk
r` } z$t|drL|jdkrLt |W 5 d}~X Y nX |	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rp|	d|d< |d }
|
|	 }| dkrpt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rt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 ]}|	d	d}zt| |d }W n tjk
rf   Y q(Y nX t ||}|d! !|	d"|j|j"|d# |d$ |j|krd%nd&d' q(|d! j#d(d d t |d)}|d# r|d* 	d+}|r||d d,< |
t$|  |s.d-d |	d!g D }||d!< ||fS ).zGet 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   rL   i  Nrc   ZaccountInfor+   r)   r%   rd   r-   )r+   r%   r,   r-   re   r/   T)r9   r:   r;   rf   r3   r9   )Zcontract_iddate)Z	error_msgZ
error_code
   rg   r2   c                 S   s   g | ]}|d  s|d qS )rU   r%   rD   rj   rD   rD   rE   rF     s   z#simulate_status.<locals>.<listcomp>c                 S   s   | d S )Nr%   rD   rm   rD   rD   rE   ro     rp   z!simulate_status.<locals>.<lambda>rq   ZresourceEntitlementsrs   r5   r   r&   r   rK   rJ   )r%   r(   r&   r   rU   c                 S   s   |  ddS rl   rh   rm   rD   rD   rE   ro     rp   rt   ru   rv   r.   c                 S   s    g | ]}| d ddkr|qS r   rh   rA   rD   rD   rE   rF     s   )%rx   ry   rz   r   r   ZContractAPIErrorr   rL   ZAttachInvalidTokenErrorri   r{   r   nowr   ZutcZtotal_secondsr   ZE_ATTACH_FORBIDDEN_EXPIREDr   strftimer   eventerrorr@   r%   infoZSTATUS_TOKEN_NOT_VALIDZE_ATTACH_FORBIDDEN_NOT_YETr   r}   r   r~   r   r   r(   r   r   )rN   r   r   r   r   Zcontract_informationeZcontract_infoZaccount_infor   Zexpiration_datetimeZdeltarM   Zeffective_datetimer   rQ   r   rk   r   rG   Zentitlement_informationrt   rv   r   rD   rD   rE   simulate_status  s    






 

 


r   )stringrI   c                 C   s   t j rt| | S | S )z=Return colorized string if using a tty, else original string.)sysstdoutisattySTATUS_HUMANIZE_COLORIZEri   )r   rD   rD   rE   for_human_colorized%  s    r   )commandsrI   c                 C   st   d}| D ]}|r|d7 }|d |7 }qd tj|td dd}d|krTd	}d
}nd}d}djtj|||tjdS )Nr)   z &&  z \
   z  )widthZsubsequent_indentr   z{
  z
}z{ z }z%{color}{prefix}{content}{suffix}{end})Zcolorprefixcontentsuffixend)jointextwrapZwrapr   r   r#   DISABLEGREYENDC)r   r   cmdZwrapped_contentr   r   rD   rD   rE   colorize_commands.  s0      r   )column_dataheaderrI   c                    sh   g }|r| | tdd | D }|dkrPd| | fdd| D  n|dd | D  |S )zReturn 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rB   ZpairrD   rD   rE   rF   U  s     z.get_section_column_content.<locals>.<listcomp>r   z{{:>{}}}: {{}}c                    s   g | ]} j | qS rD   )r   r   templaterD   rE   rF   X  s     c                 S   s   g | ]}|d  qS )r   rD   r   rD   rD   rE   rF   [  s     )r   maxr   extend)r   r   r   Ztemplate_lengthrD   r   rE   get_section_column_contentJ  s    

r   )r3   rI   c                 C   s:   | d krt jS z|  } W n tk
r.   Y nX | dS )Nz%c %Z)r   ZSTATUS_CONTRACT_EXPIRES_UNKNOWNZ
astimezone	Exceptionr   )r3   rD   rD   rE   format_expires_  s    r   )r'   r   rI   c                 C   s@  |  ds|  drv|  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f | qTd|S |  ddstjg}ntjtjtjtj	dg}|  dg D ]Z}| d}|r|n
| d	d
}| ddkrtjntj}|
tj| dd
||d q|  d}|r2|
tj || |  dr|
dtj  t|  di  D ]\}}	|
d||	 qb|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stjg}ndtg}|  dg D ]N}| dd
}| d}|r.|n
| d	d
}| dd
t|t| dd
|d}| dd}|dk	r| dd}|dk	r|

| | d}|r|sd}d|d |d< |
tjf | |r|rt| D ]h\}\}}|t |d krdnd}|
t!j|| dt| dd
t| dd
| d	d
d qq|rv|
d
 |
tj" |  dst |
dkr|
d
 |
tj |  d}|r|| t |
dkr||
 |  dr&|
dtj  t|  di  D ]\}}	|
d||	 q|
d
 |sV|rJ|
tj# n|
tj |
tj$jdd  g }|  d!i  dd"}|r|
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 |r6|
d
 |t*|d( d|S ))z&Format status dict for tabular output.r1   r;   r5   N)r%   rU   r&   r   r(   r   )r%   rU   r(   rT   r(   r)   rU   rK   r%   r   r8   z{}: {}Fr&   r'   r$   rW   rM   rX   Tz{}*r   u   ├u   └)markerr%   r&   r'   r(   r   zpro enable <service>)Zcommandr:   unknownr9   r4   Zfreer3   r.   )r   )+ri   r   ZSTATUS_NO_SERVICES_AVAILABLESTATUS_SIMULATED_TMPLr   STATUS_SERVICEZSTATUS_AVAILABLESTATUS_ENTITLEDZSTATUS_AUTO_ENABLEDSTATUS_DESCRIPTIONr   r   STATUS_UNATTACHED_TMPLZSTANDALONE_YESZSTANDALONE_NOZSTATUS_NOTICESr   ZSTATUS_FEATURESr}   r_   ZSTATUS_ALL_HINTZE_UNATTACHEDr@   r   r   r   r   Z)LIVEPATCH_KERNEL_NOT_SUPPORTED_UNATTACHEDSTATUS_HEADERr   STATUS_TMPL	enumerater   VARIANT_STATUS_TMPLZSTATUS_SERVICE_HAS_VARIANTSZSTATUS_ALL_HINT_WITH_VARIANTSZ"STATUS_FOOTER_ENABLE_SERVICES_WITHZSTATUS_FOOTER_ACCOUNTZSTATUS_FOOTER_SUBSCRIPTIONZSTATUS_FOOTER_VALID_UNTILr   ZSTATUS_FOOTER_SUPPORT_LEVELr   )r'   r   r   rC   r   r(   rU   r   rr   r`   Zservice_warningsZhas_variantsra   r&   Zfmt_argsrW   Zwarning_messagerX   idx_Zvariantr   ZpairsZaccount_nameZcontract_namer.   rD   rD   rE   format_tabulari  s6   
	
























 
r   c           
   	   C   s   t | }d}t }||d< |D ]V}|d |ks<|d|krzt| |d d}W n tjk
rj   Y qY nX |} qvq|dkrtj|dt| jrt	|i | }|d }|d |d< ||d< n"|d rt
jj}	nt
jj}	|	|d< |j|d	< |S )
zReturn 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   rs   )r%   r'   r&   rU   help)r   r   ri   r   r   r~   ZNoHelpContentr   r   rO   r   r   r`   r\   Z	help_info)
rN   r%   r   Zhelp_resourceZresponse_dictrk   Zhelp_entra   Z
status_msgrU   rD   rD   rE   r   %  s2    




r   )F)F)N)F)rrx   Zloggingr   r   collectionsr   r   r   enumr   typingr   r   r   r	   r
   Zuaclientr   r   r   r   r   r   r   Z(uaclient.api.u.pro.status.is_attached.v1r   Zuaclient.configr   r   Zuaclient.contractr   r   Zuaclient.defaultsr   r   Zuaclient.entitlementsr   Z(uaclient.entitlements.entitlement_statusr   r   r   r   Zuaclient.filesr   r   r    r!   Zuaclient.files.noticesr"   Zuaclient.messagesr#   Zget_event_loggerr   Z	getLoggerZreplace_top_level_logger_name__name__r   Z	ESSENTIALZSTANDARDZADVANCEDr   r`   ZOKGREENZSTATUS_STATUS_ENABLEDr   r   ZFAILZSTATUS_STATUS_DISABLEDr]   r   ZSTATUS_STATUS_INAPPLICABLEr\   ZSTATUS_STATUS_UNAVAILABLEr^   ZWARNINGYELLOWZSTATUS_STATUS_WARNINGZENTITLEDZSTATUS_ENTITLED_ENTITLEDr[   ZSTATUS_ENTITLED_UNENTITLEDZSTATUS_SUPPORT_ESSENTIALZSTATUS_SUPPORT_STANDARDZSTATUS_SUPPORT_ADVANCEDr   r   r   r   r   r   ZSTATUS_STATUSr   r   r   r   Zget_versionr   rz   rH   strrO   r   r   r   boolr'   r   intr   r   r   r   r   r   r   rD   rD   rD   rE   <module>   s
  $	   (
 
;G./ 
  x	  
 =