o
    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]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}|st| }dd t|dd dD }|D ]$}zt| |dd	d}	W n
 tjy   Y qw |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rt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 ]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$|  |sd-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   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 )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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stjg}nt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|rt| D ]4\}\}}|t |d krdnd}|
t!j|| dt| dd
t| dd
| d	d
d qqq|r|
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
 |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 )
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   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	
 
 =