U
    lHJev                     @   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	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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) d dl*m+Z+ d dl,m-Z- e. Z/e0e1e2Z3dZ4dZ5dZ6e&j7j8e-j9ej: e-j; e&j<j8e-j=ej> e-j; e&j?j8e-j@ejA e-j; e&jBj8e-j@ejC e-j; e&jDj8e-jEejF e-j; e#jGj8e-j9ejH e-j; e#jIj8e-j@ejJ e-j; e4e-j9ejK e-j; e5e-j9ejL e-j; e6e-j9ejM e-j; i
ZNdZOdZPdjQejRejSejTejUdZVdZWdZXddeY dddddg e%j<j8ejZi g dddg e&j?j8ddddg dddZ[dd  Z\e
e]e	f d!d"d#Z^ee
e]e	f d$d%d&Z_ee
e]e	f d$d'd(Z`e
e]e	f d!d)d*Zae
e]e	f d!d+d,ZbdGeece
e]e	f d-d.d/Zdee
e]e	f  e]e
e]e	f d0d1d2ZedHe]ecee
e]e	f eff d3d4d5Zge]e]d6d7d8Zheee]  e]d9d:d;ZidIeee]e]f  ee] ee] d<d=d>Zjee e]d?d@dAZkdJe
e]e	f ece]dBdCdDZldEdF ZmdS )K    N)OrderedDict)datetimetimezone)AnyDictListOptionalTuple)event_logger
exceptions	livepatch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)noticesstate_files)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 r@   1/usr/lib/python3/dist-packages/uaclient/status.py
<listcomp>   s   
z,_get_blocked_by_services.<locals>.<listcomp>)Zblocking_incompatible_services)entr@   r@   rA   _get_blocked_by_services   s    rD   )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)r>   r;   Zvariant_clsrK   inapplicable_resourcesr@   rA   
<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<   rU   itemsrD   Zpresentation_namer$   valuer:   )rC   rN   rK   rT   rP   rQ   rW   rR   rU   Z
ent_statusZdetailsrS   service_statusr@   rM   rA   rL      sL    



	rL   )rK   rE   c                 C   s  t tj t tj tt}| jd }|d }t	j
j}||d d|dt  pZg |d |d |dd	|d
g |d| jjd | jjd | jjdd	| jjdg dd |dr| j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k
rZ   Y q Y nX || }	|d t|	||  q |d jdd d | jjdi d}
|
r|
di d}|r||d  d!< |S )"z8Return configuration of attached status as a dictionary.machineTokenInfocontractInfoZ	machineIdTr0   r'   r!   	createdAtr%   r)   r&   externalAccountIDsr+   )r,   r-   r0   r   r5   r6   effectiveTor/   effectiveFromr.   ZavailableResourcesc                 S   s&   i | ]}| d s|d | dqS )rR   r!   r$   getr>   resourcer@   r@   rA   rO      s   
 z$_attached_status.<locals>.<dictcomp>c                 S   s   |  ddS Nr!   r%   re   xr@   r@   rA   <lambda>       z"_attached_status.<locals>.<lambda>keyrK   r!   r1   c                 S   s   |  ddS ri   re   rj   r@   r@   rA   rl   
  rm   supportr9   affordancessupportLevelr5   r*   )r   remover   ZAUTO_ATTACH_RETRY_FULL_NOTICEZAUTO_ATTACH_RETRY_TOTAL_FAILUREcopydeepcopyDEFAULT_STATUSZmachine_tokenr   rZ   r]   updaterf   listZmachine_token_filer6   Zcontract_expiry_datetimer   sortedr   r   EntitlementNotFoundErrorappendrL   sortentitlements)rK   responser_   r`   r*   	resourcesrN   rh   ent_clsrC   rq   rs   r@   r@   rA   _attached_status   sz    






  

 


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.rR   r!   r%   rp   z@Ignoring availability of unknown service %s from contract serverzwithout a 'name' keyr   Nr1   presentedAs)r!   r$   rQ   rR   c                 S   s   |  ddS ri   re   rj   r@   r@   rA   rl   B  rm   z$_unattached_status.<locals>.<lambda>rn   )ru   rv   rw   r   rf   r   	AVAILABLEr]   rY   r   r   r{   LOGdebugr!   r   on_supported_kernelLivepatchSupportUNSUPPORTEDrV   r|   r$   r}   )rK   r   r   rh   rR   r   Zlpdescr_overrider@   r@   rA   _unattached_status  sF    


 




r   c           
   	   C   s   t j| jdd}||O }|r |S t|}g }|di D ]j}|d }zt| |d}W n$ tjk
rz   |	| Y q:Y nX t
jj}	|jr|dd|	kr:|	| q:|r||d< |S )z1Remove beta services from response dict if neededzfeatures.allow_beta)configZpath_to_valuer1   r!   rp   r#   r%   )r   Zis_config_value_truerK   ru   rv   rf   r   r   r{   r|   r   ACTIVEr]   is_beta)
rK   show_allr   Zconfig_allow_betaZnew_responseZreleased_resourcesrh   resource_namer   Zenabled_statusr@   r@   rA   _handle_beta_resourcesG  s,     


r   c                 C   s   t }|jj}tj}|  \}}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}i }	tD ]}
t| |
rt| |
|	|
< 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)r2   r3   r   Zconfig_pathr   r4   r   	ua_config)r   INACTIVEr]   r   NO_ACTIVE_OPERATIONSZcheck_lock_infor   ry   r   Z	LOCK_HELDformatr   Zreboot_cmd_marker_fileZ
is_presentZREBOOTREQUIREDZENABLE_REBOOT_REQUIRED_TMPLZcfg_pathrK   r4   r   hasattrgetattr)rK   Z
userStatusZ
status_valZstatus_descZlock_pidr   Znotices_listr   retr   ro   r@   r@   rA   _get_config_statusk  s<    	 	
r   )rK   r   rE   c                 C   sp   t | jrt| }nt| }|t|  t r>| d| t	| ||}|sld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.
    zstatus-cachec                 S   s    g | ]}| d ddkr|qS rR   rG   re   r=   r@   r@   rA   rB     s   zstatus.<locals>.<listcomp>r1   )r   is_attachedr   r   rx   r   r   Zwe_are_currently_rootZwrite_cacher   rf   )rK   r   r   available_servicesr@   r@   rA   r#     s    	


r#   )r~   entitlement_namerE   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"   rG   rF   ZobligationsZenableByDefaultrr   )r"   auto_enabledrr   re   )r~   r   r9   r@   r@   rA   _get_entitlement_information  s    
r   )tokenr   rE   c              
   C   sL  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 || d!}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$|  t%| ||}|sDd.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   rH   i  Nr`   ZaccountInfor'   r%   r!   ra   r)   )r'   r!   r(   r)   rb   r+   T)r5   r6   r7   rc   r/   r5   )Zcontract_iddate)Z	error_msgZ
error_code
   rd   r.   c                 S   s   g | ]}|d  s|d qS )rR   r!   r@   rg   r@   r@   rA   rB     s   z#simulate_status.<locals>.<listcomp>c                 S   s   | d S )Nr!   r@   rj   r@   r@   rA   rl     rm   z!simulate_status.<locals>.<lambda>rn   ZresourceEntitlementsrp   rJ   r1   r   r"   r   rG   rF   )r!   r$   r"   r   rR   c                 S   s   |  ddS ri   re   rj   r@   r@   rA   rl   *  rm   rq   rr   rs   r*   c                 S   s    g | ]}| d ddkr|qS r   re   r=   r@   r@   rA   rB   6  s   )&ru   rv   rw   r   r   ZContractAPIErrorr   rH   ZAttachInvalidTokenErrorrf   rx   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   rz   r   r{   r   r|   r$   r}   r   r   )rK   r   r   r   r   Zcontract_informationeZcontract_infoZaccount_infor   Zexpiration_datetimeZdeltarI   Zeffective_datetimer   rN   r~   rh   r   r   rC   Zentitlement_informationrq   rs   r   r@   r@   rA   simulate_status  s    






 


 


r   )stringrE   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_COLORIZErf   )r   r@   r@   rA   for_human_colorized@  s    r   )commandsrE   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   r@   r@   rA   colorize_commandsI  s0      r   )column_dataheaderrE   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r>   Zpairr@   r@   rA   rB   p  s     z.get_section_column_content.<locals>.<listcomp>r   z{{:>{}}}: {{}}c                    s   g | ]} j | qS r@   )r   r   templater@   rA   rB   s  s     c                 S   s   g | ]}|d  qS )r   r@   r   r@   r@   rA   rB   v  s     )r|   maxr   extend)r   r   r   Ztemplate_lengthr@   r   rA   get_section_column_contente  s    

r   )r/   rE   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   )r/   r@   r@   rA   format_expiresz  s    r   )r#   r   rE   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.r-   r7   r1   N)r!   rR   r"   r   r$   r   )r!   rR   r$   rQ   r$   r%   rR   rG   r!   r   r4   z{}: {}Fr"   r#   r    rT   rI   rU   Tz{}*r   u   ├u   └)markerr!   r"   r#   r$   r   zpro enable <service>)Zcommandr6   unknownr5   r0   Zfreer/   r*   )r   )+rf   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_FEATURESrz   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   r?   r   r$   rR   r   ro   r]   Zservice_warningsZhas_variantsr^   r"   Zfmt_argsrT   Zwarning_messagerU   idx_Zvariantr   ZpairsZaccount_nameZcontract_namer*   r@   r@   rA   format_tabular  s6   
	
























 
r   c              	   C   s  t | }d}t }||d< |D ]^}|d |ks<|d|krzt| |d d}W n tjk
rj   Y qY nX |}|| } q~q|dkrtj|dt| jrt	|i | }|d }	|d |d< |	|d< |	dkr|j
rd	|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   rp   )r!   r#   r"   enabledTZbetarR   help)r   r   rf   r   r   r{   ZNoHelpContentr   r   rL   r   r   r   r]   rY   Z	help_info)rK   r!   r   Zhelp_resourceZresponse_dictrh   Zhelp_ent_clsZhelp_entr^   Z
status_msgrR   r@   r@   rA   r   @  s>     





r   )F)F)N)F)nru   Zloggingr   r   collectionsr   r   r   typingr   r   r   r   r	   Zuaclientr
   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   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_DISABLEDrZ   r   ZSTATUS_STATUS_INAPPLICABLErY   ZSTATUS_STATUS_UNAVAILABLEr[   ZWARNINGYELLOWZSTATUS_STATUS_WARNINGZENTITLEDZSTATUS_ENTITLED_ENTITLEDrX   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   rw   rD   strrL   r   r   r   r   boolr#   r   intr   r   r   r   r   r   r   r@   r@   r@   rA   <module>   s
      (
 
;H1$+! 
  z	  
 =