U
    2d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	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&j7j8 e-j: e&j;j8e-j<e&j;j8 e-j: e&j=j8e-j>e&j=j8 e-j: e&j?j8e-j>e&j?j8 e-j: e&j@j8e-jAe&j@j8 e-j: e#jBj8e-j9e#jBj8 e-j: e#jCj8e-j>e#jCj8 e-j: e4e-j9e4 e-j: e5e-j9e5 e-j: e6e-j9e6 e-j: i
ZDdZEdZFdZGdZHdZIddeJ dddddg e%j;j8ejKi g dddg e&j=j8ddddg dddZLdd ZMe
eNe	f d d!d"ZOee
eNe	f d#d$d%ZPee
eNe	f d#d&d'ZQe
eNe	f d d(d)ZRe
eNe	f d d*d+ZSdFeeTe
eNe	f d,d-d.ZUee
eNe	f  eNe
eNe	f d/d0d1ZVdGeNeTee
eNe	f eWf d2d3d4ZXeNeNd5d6d7ZYeeeN  eNd8d9d:ZZdHeeeNeNf  eeN eeN d;d<d=Z[ee eNd>d?d@Z\dIe
eNe	f eTeNdAdBdCZ]dDdE Z^dS )J    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: <14}{description}z0SERVICE          ENTITLED  STATUS    DESCRIPTIONz4{name: <17}{entitled: <19}{status: <19}{description}z={marker} {name: <15}{entitled: <19}{status: <19}{description}zUContent provided in json response is currently considered Experimental and may changez0.1F idname
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>y   s   
z,_get_blocked_by_services.<locals>.<listcomp>)Zblocking_incompatible_services)entr<   r<   r=   _get_blocked_by_servicesx   s    r@   )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:   r7   Zvariant_clsrG   inapplicable_resourcesr<   r=   
<dictcomp>   s    z,_attached_service_status.<locals>.<dictcomp>)	r#   descriptionentitledstatusstatus_detailsdescription_override	available
blocked_bywarningvariants)status_description_overridecontract_statusr#   r   
UNENTITLEDr   UNAVAILABLEINAPPLICABLEZuser_facing_statusWARNINGr8   rT   itemsr@   Zpresentation_namerL   valuer6   )r?   rJ   rG   rS   rO   rP   rV   rQ   rT   Z
ent_statusZdetailsrR   service_statusr<   rI   r=   rH      sL    



	rH   )rG   rA   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	machineIdTr,   r"   r#   	createdAtr    r%   r!   externalAccountIDsr'   )r(   r)   r,   r   r1   r2   effectiveTor+   effectiveFromr*   ZavailableResourcesc                 S   s&   i | ]}| d s|d | dqS )rQ   r#   rL   getr:   resourcer<   r<   r=   rK      s   
 z$_attached_status.<locals>.<dictcomp>c                 S   s   |  ddS Nr#   r    rd   xr<   r<   r=   <lambda>       z"_attached_status.<locals>.<lambda>keyrG   r#   r-   c                 S   s   |  ddS rh   rd   ri   r<   r<   r=   rk      rl   supportr5   affordancessupportLevelr1   r&   )r   remover   ZAUTO_ATTACH_RETRY_FULL_NOTICEZAUTO_ATTACH_RETRY_TOTAL_FAILUREcopydeepcopyDEFAULT_STATUSZmachine_tokenr   rY   r\   updatere   listZmachine_token_filer2   Zcontract_expiry_datetimer   sortedr   r   EntitlementNotFoundErrorappendrH   sortentitlements)rG   responser^   r_   r&   	resourcesrJ   rg   ent_clsr?   rp   rr   r<   r<   r=   _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 n6 t
jk
r   ttjj|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.rQ   r#   r    ro   zwithout a 'name' key)r;   r   Nr-   presentedAs)r#   rL   rP   rQ   c                 S   s   |  ddS rh   rd   ri   r<   r<   r=   rk   4  rl   z$_unattached_status.<locals>.<lambda>rm   )rt   ru   rv   r   re   r   	AVAILABLEr\   rX   r   r   rz   LOGdebugr   Z!AVAILABILITY_FROM_UNKNOWN_SERVICEformatr#   r   on_supported_kernelLivepatchSupportUNSUPPORTEDrU   r{   rL   r|   )rG   r~   r   rg   rQ   r   Zlpdescr_overrider<   r<   r=   _unattached_status  sH    


 




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_valuer-   r#   ro   rN   r    )r   Zis_config_value_truerG   rt   ru   re   r   r   rz   r{   r   ACTIVEr\   is_beta)
rG   show_allr~   Zconfig_allow_betaZnew_responseZreleased_resourcesrg   resource_namer   Zenabled_statusr<   r<   r=   _handle_beta_resources9  s,     


r   c                 C   s   t }|jj}tj}|  \}}t p(g }|dkrN|jj}tj	j
||dj}n"tjjrp|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)r.   r/   r   Zconfig_pathr   r0   r   	ua_config)r   INACTIVEr\   r   NO_ACTIVE_OPERATIONSZcheck_lock_infor   rx   r   Z	LOCK_HELDr   r8   r   Zreboot_cmd_marker_fileZ
is_presentZREBOOTREQUIREDZENABLE_REBOOT_REQUIRED_TMPLZcfg_pathrG   r0   r   hasattrgetattr)rG   Z
userStatusZ
status_valZstatus_descZlock_pidr   Znotices_listr   retr   rn   r<   r<   r=   _get_config_status]  s<    	 
	
r   )rG   r   rA   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 rQ   rC   rd   r9   r<   r<   r=   r>     s   zstatus.<locals>.<listcomp>r-   )r   is_attachedr   r   rw   r   r   Zwe_are_currently_rootZwrite_cacher   re   )rG   r   r~   available_servicesr<   r<   r=   rN     s    	


rN   )r}   entitlement_namerA   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.typerM   rC   rB   ZobligationsZenableByDefaultrq   )rM   auto_enabledrq   rd   )r}   r   r5   r<   r<   r=   _get_entitlement_information  s    
r   )tokenr   rA   c              
   C   sN  d}t t}zt| |}W nR tjk
rn } z2t|drZ|jdkrZtjt	j
jt	j
jd|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rx|d|d< |d }
|
|	 }| dkrxt	jj|d d |
td}tj|j|jd td|j d  d}|dr|d|d< |d }|	| }| dkrt	jj|d d |td}tj|j|jd t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
rh   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%| ||}|sFd0d |d$g D }||d$< ||fS )1zGet 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   rD   i  )r8   Zmsg_codeNr_   ZaccountInfor"   r    r#   r`   r%   )r"   r#   r$   r%   ra   r'   T)r1   r2   r3   rb   r+   r1   )Zcontract_iddate)Z	error_msgZ
error_codezThis token is not valid.

   rc   r*   c                 S   s   g | ]}|d  s|d qS )rQ   r#   r<   rf   r<   r<   r=   r>     s   z#simulate_status.<locals>.<listcomp>c                 S   s   | d S )Nr#   r<   ri   r<   r<   r=   rk     rl   z!simulate_status.<locals>.<lambda>rm   ZresourceEntitlementsro   rF   r-   r   rM   r   rC   rB   )r#   rL   rM   r   rQ   c                 S   s   |  ddS rh   rd   ri   r<   r<   r=   rk     rl   rp   rq   rr   r&   c                 S   s    g | ]}| d ddkr|qS r   rd   r9   r<   r<   r=   r>   '  s   )&rt   ru   rv   r   r   ZContractAPIErrorr   rD   UserFacingErrorr   ZATTACH_INVALID_TOKENr8   r#   re   rw   r   nowr   ZutcZtotal_secondsZATTACH_FORBIDDEN_EXPIREDr   strftimer   eventerrorinfoZATTACH_FORBIDDEN_NOT_YETr   ry   r   rz   r   r{   rL   r|   r   r   )rG   r   r   r   r~   Zcontract_informationeZcontract_infoZaccount_infor   Zexpiration_datetimeZdeltarE   Zeffective_datetimer   rJ   r}   rg   r   r   r?   Zentitlement_informationrp   rr   r   r<   r<   r=   simulate_status  s    






 


 


r   )stringrA   c                 C   s   t j rt| | S | S )z=Return colorized string if using a tty, else original string.)sysstdoutisattySTATUS_COLORre   )r   r<   r<   r=   colorize1  s    r   )commandsrA   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<   r=   colorize_commands6  s0      r   )column_dataheaderrA   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<   r=   r>   ]  s     z.get_section_column_content.<locals>.<listcomp>r   z{{:>{}}}: {{}}c                    s   g | ]} j | qS r<   )r   r   templater<   r=   r>   `  s     c                 S   s   g | ]}|d  qS )r   r<   r   r<   r<   r=   r>   c  s     )r{   maxr   extend)r   r   r   Ztemplate_lengthr<   r   r=   get_section_column_contentR  s    

r   )r+   rA   c                 C   s8   | d krdS z|   } W n tk
r,   Y nX | dS )NzUnknown/Expiredz%c %Z)Z
astimezone	Exceptionr   )r+   r<   r<   r=   format_expiresg  s    r   )rN   r   rA   c                 C   s  |  ds|  drl|  dds(tjS tjddddd	d
g}|  dg D ]}|tjf | qJd|S |  ddstjg}nhtjddd	dg}|  dg D ]H}| d}|r|n
| dd}|tj| dd| dd|d q|  d}|r|d || |  drV|d t	|  di 
 D ]\}}|d|| q8|sl|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	rl| dd}|dk	rl|	| | d}|r|sd}
d|d |d< |tjf | |r|rt|
 D ]h\}\}}|t|d  krd!nd"}|tj|| dt| ddt| dd| ddd# qq|
rL|d |tj |  dsft|	d$kr|d |d |  d}|r|| t|	d$kr||	 |  dr|d t	|  di 
 D ]\}}|d|| q|d |s$|
r|tj n|tj |d% g }|  d&i  dd'}|rZ|d(|f |  d)i  dd'}|r|d*|f |  d+dd,kr|d-t|  d.f |  d)i  d/d'}|d0t|f |r|d |t|d1 d|S )2z&Format status dict for tabular output.r)   r3   r-   NZSERVICEr   ENTITLEDZAUTO_ENABLEDZDESCRIPTION)r#   rQ   rM   r   rL   r   )r#   rQ   rL   rP   rL   r    r#   rQ   r   ZNOTICESr0   z	
FEATURESz{}: {}FrM   rN   )r#   rM   rN   rL   rS   rE   rT   Tz{}*r   u   ├u   └)markerr#   rM   rN   rL   r   z*Enable services with: pro enable <service>r2   unknownZAccountr1   ZSubscriptionr,   ZfreezValid untilr+   r&   zTechnical support level)r   )re   r   ZSTATUS_NO_SERVICES_AVAILABLESTATUS_SIMULATED_TMPLr   r{   r   STATUS_UNATTACHED_TMPLr   ry   r[   ZSTATUS_ALL_HINTZ
UNATTACHEDr8   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_VARIANTSr   r   )rN   r   r   r;   r   rL   r   rn   r\   Zservice_warningsZhas_variantsr]   rM   Zfmt_argsrS   Zwarning_messagerT   idx_Zvariantr   ZpairsZaccount_nameZcontract_namer&   r<   r<   r=   format_tabularq  s
   
	




























 
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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: UserFacingError when no help is available.
    Nr#   r   ro   zNo help available for '{}'rN   rM   enabledTZbetarQ   help)r   r   re   r   r   rz   r   r   r   r   rH   r   r   r   r\   rX   Z	help_info)rG   r#   r   Zhelp_resourceZresponse_dictrg   Zhelp_ent_clsZhelp_entr]   Z
status_msgrQ   r<   r<   r=   r     sB     





r   )F)F)N)F)_rt   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OKGREENr   r   ZFAILrY   r   rX   rZ   ZWARNINGYELLOWr   rW   r   r   r   r   r   r   Zget_versionr   rv   r@   strrH   r   r   r   r   boolrN   r   intr   r   r   r   r   r   r   r<   r<   r<   r=   <module>   s         
;H1$+! 
  y  
 $