o
    ϴfq                     @   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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-m.Z. d dl/m0Z0 e1 Z2e3e4e5Z6dZ7dZ8dZ9e'j:j;e0j<ej= e0j> e'j?j;e0j@ejA e0j> e'jBj;e0jCejD e0j> e'jEj;e0jCejF e0j> e'jGj;e0jHejI e0j> e$jJj;e0j<ejK e0j> e$jLj;e0jCejM e0j> e7e0j<ejN e0j> e8e0j<ejO e0j> e9e0j<ejP e0j> i
ZQdZRdZSdjTejUejVejWejXdZYdZZdZ[i ddddde\ ddddd dd!dd"dd#g d$e&j?j;d%ej]d&i d'g d(d)d)d)g e'jBj;d*d+d)d)d)g d,d-dZ^d.d/ Z_d0e
e`e	f fd1d2Zad3ed0e
e`e	f fd4d5Zbd3ed0e
e`e	f fd6d7Zcd0e
e`e	f fd8d9ZddTd3ed:eed0e
e`e	f fd;d<Zfd=ee
e`e	f  d>e`d0e
e`e	f fd?d@Zg	dTdAe`d:eed0ee
e`e	f ehf fdBdCZidDe`d0e`fdEdFZjdGeee`  d0e`fdHdIZk	dUdJeee`e`f  dKee` d0ee` fdLdMZld!ee d0e`fdNdOZmdTd<e
e`e	f d:eed0e`fdPdQZndRdS ZodS )V    N)OrderedDict)datetimetimezone)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'   r9   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 rK   1/usr/lib/python3/dist-packages/uaclient/status.py
<listcomp>   s    

z,_get_blocked_by_services.<locals>.<listcomp>)blocking_incompatible_services)entrK   rK   rL   _get_blocked_by_services   s   
rP   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 )	Nr7   noyes)codemessagec                    s$   i | ]\}}|t | d  qS ))cfg)_attached_service_status)rI   rE   variant_clsrV   inapplicable_resourcesrK   rL   
<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WARNINGrG   ra   itemsrP   presentation_namer*   valuerD   )rO   rZ   rV   r`   r\   r]   rc   r^   ra   
ent_statusdetailsr_   service_statusrK   rY   rL   rW      sL   



	rW   rV   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	machineIdTr1   r9   r'   	createdAtr7   r;   r8   externalAccountIDsr>   )r-   r.   r1   r   r6   r=   effectiveTor0   effectiveFromr/   availableResourcesc                 S   s&   i | ]}| d s|d | dqS )r^   r'   r*   getrI   resourcerK   rK   rL   r[     s    z$_attached_status.<locals>.<dictcomp>c                 S      |  ddS Nr'   r7   rw   xrK   rK   rL   <lambda>      z"_attached_status.<locals>.<lambda>keyrV   r'   r2   c                 S   r{   r|   rw   r}   rK   rK   rL   r     r   supportrC   affordancessupportLevelr6   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   rf   rk   updaterx   listr=   contract_expiry_datetimer   sortedr   r   EntitlementNotFoundErrorappendrW   sortentitlements)rV   responsemachine_token_filero   rp   r<   	resourcesrZ   rz   rO   r   r   rK   rK   rL   _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'   r7   r   z@Ignoring availability of unknown service %s from contract serverzwithout a 'name' keyr   Nr2   presentedAs)r'   r*   r]   r^   c                 S   r{   r|   rw   r}   rK   rK   rL   r   F  r   z$_unattached_status.<locals>.<lambda>r   )r   r   r   r   rx   r   	AVAILABLErk   re   r   r   r   LOGdebugr'   r   on_supported_kernelLivepatchSupportUNSUPPORTEDrb   r   r*   r   )rV   r   r   rz   r^   rO   descr_overriderK   rK   rL   _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| |
r_|	|
 du r_t| |
|	|
< 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)r3   r4   r   config_pathconfigr5   Nr   	ua_config)r   INACTIVErk   r   NO_ACTIVE_OPERATIONSr   check_lock_infor   r   ACTIVE	LOCK_HELDformatr   reboot_cmd_marker_file
is_presentREBOOTREQUIREDENABLE_REBOOT_REQUIRED_TMPLcfg_pathrV   r5   r    user_configpublic_configto_dictr   hasattrgetattr)rV   
userStatus
status_valstatus_desclock_pidr   notices_listr   retr   r   rK   rK   rL   _get_config_statusK  s<   		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^   rS   rw   rH   rK   rK   rL   rM     
    zstatus.<locals>.<listcomp>r2   )r   is_attachedr   r   r   r   r   we_are_currently_rootr   status_cache_filewriterx   )rV   r   r   available_servicesrK   rK   rL   r)   v  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(   rS   rR   obligationsenableByDefaultr   )r(   auto_enabledr   rw   )r   r   rC   rK   rK   rL   _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   rT   i  Nrp   accountInfor9   r7   r'   rr   r;   )r9   r'   r:   r;   rs   r>   T)r6   r=   r@   rt   r0   r6   )contract_iddate)	error_msg
error_code
   ru   r/   c                 S   s   g | ]
}|d  s|d qS )r^   r'   rK   ry   rK   rK   rL   rM     s    z#simulate_status.<locals>.<listcomp>c                 S   s   | d S )Nr'   rK   r}   rK   rK   rL   r     s    z!simulate_status.<locals>.<lambda>r   resourceEntitlementsr   r2   r   r(   r   rS   rR   )r'   r*   r(   r   r^   c                 S   r{   r|   rw   r}   rK   rK   rL   r     r   r   r   r   r<   c                 S   r   r   rw   rH   rK   rK   rL   rM     r   )%r   r   r   r   r   ContractAPIErrorr   rT   AttachInvalidTokenErrorrx   r   r   nowr   utctotal_secondsr   E_ATTACH_FORBIDDEN_EXPIREDr   strftimer   eventerrorrG   r'   infoSTATUS_TOKEN_NOT_VALIDE_ATTACH_FORBIDDEN_NOT_YETr   r   r   r   r   r   r*   r   r   )rV   r   r   r   r   contract_informationecontract_infoaccount_infor   expiration_datetimedeltarU   effective_datetimer   rZ   r   rz   r   rO   entitlement_informationr   r   r   rK   rK   rL   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_COLORIZErx   )r   rK   rK   rL   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 )Nr7   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   rK   rK   rL   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rI   pairrK   rK   rL   rM   P  s    z.get_section_column_content.<locals>.<listcomp>r   z{{:>{}}}: {{}}c                    s   g | ]} j | qS rK   )r   r
  templaterK   rL   rM   S  s    c                 S   s   g | ]}|d  qS )r   rK   r
  rK   rK   rL   rM   V  s    )r   maxr   extend)r  r  r   template_lengthrK   r  rL   get_section_column_contentE  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   )r0   rK   rK   rL   format_expiresZ  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.   r@   r2   N)r'   r^   r(   r   r*   r   )r'   r^   r*   r]   r*   r7   r^   rS   r'   r   r5   z{}: {}Fr(   r)   r&   r`   rU   ra   Tz{}*r   u   ├u   └)markerr'   r(   r)   r*   r   zpro enable <service>)commandr=   unknownr6   r1   freer0   r<   )r  rK   )+rx   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   ri   STATUS_ALL_HINTE_UNATTACHEDrG   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   rJ   r   r*   r^   r   r   rk   service_warningshas_variantsrn   r(   fmt_argsr`   warning_messagera   idx_variantr  pairsaccount_namecontract_namer<   rK   rK   rL   format_tabulard  s4  

	




























r>  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   rx   r   r   r   NoHelpContentr   r   rW   r   r   rk   re   	help_info)
rV   r'   r   help_resourceresponse_dictrz   help_entrn   
status_msgr^   rK   rK   rL   r?     s6   



r?  )F)N)pr   loggingr   r   collectionsr   r   r   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   rk   OKGREENSTATUS_STATUS_ENABLEDr  r   FAILSTATUS_STATUS_DISABLEDrf   r  STATUS_STATUS_INAPPLICABLEre   STATUS_STATUS_UNAVAILABLErh   WARNINGYELLOWSTATUS_STATUS_WARNINGENTITLEDSTATUS_ENTITLED_ENTITLEDrd   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   rP   strrW   r   r   r   boolr)   r   intr   r   r  r  r  r>  r?  rK   rK   rK   rL   <module>   s8   $	(
	
 

;G. +


x	
 
 =