U
    0h}F                     @   sH  d Z ddlZ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
mZ ddlmZmZ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 dd	lmZ dd
lmZmZmZ dZ ej!G dd dej"Z#ej!G dd dej"Z$ej!G dd dej"Z%e&e%j'e%j(e%j)e%j*gZ+G dd deZ,dZ-ee. e/e.dddZ0d?ddZ1e#e$ee.e.f dddZ2e,dddZ3e4d d!d"Z5e/d d#d$Z6ee%e.f d d%d&Z7e/d d'd(Z8e/e/d)d*d+Z9e/d d,d-Z:e#d d.d/Z;e.d d0d1Z<d2d3 Z=d4d5 Z>eeef d d6d7Z?d@ee e/e,d9d:d;Z@d<d= ZAeBd>krDeA  dS )AzGDefine 'status' utility and handler as part of cloud-init command line.    N)deepcopy)gmtimesleepstrftime)AnyDictList
NamedTupleOptionalTuple)safeyamlsubp)read_cfg_paths)uses_systemd)Paths)get_cmdline	load_jsonload_text_filez/etc/cloud/cloud-init.disabledc                   @   s    e Zd ZdZdZdZdZdZdS )RunningStatusz=Enum representing user-visible cloud-init application status.znot startedrunningZdonedisabledN)__name__
__module____qualname____doc__NOT_STARTEDRUNNINGDONEDISABLED r   r   6/usr/lib/python3/dist-packages/cloudinit/cmd/status.pyr      s
   r   c                   @   s   e Zd ZdZdZdZdZdS )ConditionStatusz;Enum representing user-visible cloud-init condition status.errorZdegradedZhealthyN)r   r   r   r   ERRORDEGRADEDPEACHYr   r   r   r    r!   %   s   r!   c                   @   s0   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
S )EnabledStatusz<Enum representing user-visible cloud-init boot status codes.zdisabled-by-generatorzdisabled-by-kernel-command-linezdisabled-by-marker-filez disabled-by-environment-variablezenabled-by-generatorzenabled-by-kernel-command-linezenabled-by-sysvinitunknownN)r   r   r   r   DISABLED_BY_GENERATORDISABLED_BY_KERNEL_CMDLINEDISABLED_BY_MARKER_FILEDISABLED_BY_ENV_VARIABLEENABLED_BY_GENERATORENABLED_BY_KERNEL_CMDLINEENABLED_BY_SYSVINITUNKNOWNr   r   r   r    r&   .   s   r&   c                   @   sr   e Zd ZU eed< eed< eed< eed< ee ed< e	eee f ed< eed< e
e ed< e	eef ed	< d
S )StatusDetailsrunning_statuscondition_statusboot_status_codedescriptionerrorsrecoverable_errorslast_update
datasourcev1N)r   r   r   r   __annotations__r!   r&   strr   r   r
   r   r   r   r   r    r0   F   s   
r0   zextended_status: {extended_status}
boot_status_code: {boot_code}
{last_update}detail: {description}
errors:{errors}
recoverable_errors:{recoverable_errors})systemctl_argswaitreturnc                C   sB   zt  d| j W S  t jk
r:   |s. td Y q X q dS )z-Query systemd with retries and return output.	systemctl      ?N)r?   )r   stdoutstripProcessExecutionErrorr   )r<   r=   r   r   r    query_systemctlZ   s    rD   c                 C   sX   | st jddd} | jdtdddgddd	 | jd
ddddd | jdddddd | S )a%  Build or extend an arg parser for status utility.

    @param parser: Optional existing ArgumentParser instance representing the
        status subcommand which will be extended to support the args of
        this utility.

    @returns: ArgumentParser with proper argument configuration.
    statuszReport run status of cloud init)progr4   z--formatjsontabularyamlz5Specify output format for cloud-id (default: tabular))typechoicesdefaulthelpz-lz--long
store_trueFzJReport long format of statuses including run stage name and error messages)actionrL   rM   z-wz--waitz'Block waiting on cloud-init to complete)argparseArgumentParseradd_argumentr;   parserr   r   r    
get_parseri   s6    	 
rU   )r   	conditionr>   c                 C   s^   |t jkr d|j d| j fS |t jkrR| tjtjfkrR| j|j d| j fS | j| jfS )zTranslate running and condition status to human readable strings.

    Returns (status, extended_status).
    Much of this is for backwards compatibility
    r"   z -  )r!   r#   valuer$   r   r   r   )r   rV   r   r   r    translate_status   s    	
rY   )detailsc           
   
   C   s\  t |j|j\}}|j|jj|||j|j|j|j	d|j
}dt|i|d< d|d< | jdkrd}|d }t| d|  | jrX|d	rd
|d	  d}nd}|d rdd|d  nd}|d rdddd |d  D  nd}	ttj|d ||d |d |||	d n>| jdkr>ttj|dddd n| jdkrXtt| dS )zPrint status out to the CLI.)r8   r3   rE   extended_statusdetailr5   r6   r7   1ZschemasZ_schema_versionrH    rE   zstatus: r7   zlast_update: 
r5   
	- z []r6   c                 S   s.   g | ]&\}}| d d dd |D  qS )z:
	- r`   c                 S   s   g | ]}| d dqS )r_   rW   )replace).0ir   r   r    
<listcomp>   s     z+print_status.<locals>.<listcomp>.<listcomp>)join)rb   kvr   r   r    rd      s   z print_status.<locals>.<listcomp>z {}r[   r3   r\   )r[   prefixZ	boot_coder4   r7   r5   r6   rG      T),z: )indentZ	sort_keysZ
separatorsrI   N)rY   r1   r2   r8   r3   rX   r4   r5   r6   r7   r9   r   formatprintZlonggetre   itemsTABULAR_LONG_TMPLrG   dumpsr   )
argsrZ   rE   r[   Zdetails_dictrh   stater7   Zerrors_outputZrecoverable_errors_outputr   r   r    print_status   sz     	

	   rt   )r>   c                 C   s   t  }t||j}|jr`|jtjtjfkr`|jdkrJtj	
d tj	  t||j}td qt|| |jtjkrzdS |jtjkrdS dS )z4Handle calls to 'cloud-init status' as a subcommand.rH   .r@      r   )r   get_status_detailsr=   r1   r   r   r   rl   sysrA   writeflushr   rt   r2   r!   r#   r$   )namerr   pathsrZ   r   r   r    handle_status_args   s$    



r}   c                 C   s6   zt dg| d}W n tjk
r,   d}Y nX d|kS )z?Return whether cloud-init is disabled via environment variable.zshow-environmentr=   r^   cloud-init=disabled)rD   r   rC   )r=   envr   r   r    _disabled_via_environment  s
    
r   c                 C   s   t   }t stj}d}nd|kr0tj}d}ntj| rNtj	}d
| }nd|krbtj}d}ndtjddkst rt|d	rtj}d
}nRtjtj|jdrtj}d}n.tjtj|jdrtj}d}n
tj}d}||fS )aX  Report whether cloud-init current boot status

    @param disable_file: The path to the cloud-init disable file.
    @param paths: An initialized cloudinit.helpers.Paths object.
    @param wait: If user has indicated to wait for cloud-init to complete.
    @returns: A tuple containing (code, reason) about cloud-init's status and
    why.
    zCloud-init enabled on sysvinitzcloud-init=enabledz<Cloud-init enabled by kernel command line cloud-init=enabledzCloud-init disabled by {0}r   z;Cloud-init disabled by kernel parameter cloud-init=disabledZKERNEL_CMDLINEr^   r~   zNCloud-init disabled by environment variable KERNEL_CMDLINE=cloud-init=disabledr   z+Cloud-init disabled by cloud-init-generatorenabledz2Cloud-init enabled by systemd cloud-init-generatorz'Systemd generator may not have run yet.)r   splitr   r&   r.   r-   ospathexistsr*   rl   r)   environrn   r   r+   re   run_dirr(   r,   r/   )Zdisable_filer|   r=   Zcmdline_partsZbootstatus_codereasonr   r   r    get_bootstatus  s<    	
r   c                   C   s   t t jtkS )N)rw   r   r3   DISABLED_BOOT_CODESr   r   r   r    is_cloud_init_enabled8  s    
r   )r=   r>   c                 C   s   dD ]}zt dd|g| d}W nB tjk
r` } z"td|j tjd W Y  dS d}~X Y nX td	d
 | D }|d ds|d dks dS |d dkr|d dkrqq|d dkr|d dkr dS n|d dks|d dkr dS  dS dS )z2Return if systemd units report a cloud-init error.)zcloud-final.servicezcloud-config.servicezcloud-init.servicezcloud-init-local.serviceZshowz5--property=ActiveState,UnitFileState,SubState,MainPIDr~   z^Failed to get status from systemd. Cloud-init status may be inaccurate. Error from systemctl: )fileFNc                 S   s    g | ]}d d | dD qS )c                 S   s   g | ]}|  qS r   )rB   )rb   xr   r   r    rd   Z  s     z-systemd_failed.<locals>.<listcomp>.<listcomp>=)r   )rb   rr   r   r    rd   Z  s     z"systemd_failed.<locals>.<listcomp>ZUnitFileStater   ZstaticTZActiveStateZactiveZSubStateZexitedr   ZMainPID0Zfailed)	rD   r   rC   rm   stderrrx   dict
splitlines
startswith)r=   servicerA   eZstatesr   r   r    systemd_failed?  sF    




r   c                 C   s   t j| ot j| S )z%Return True if cloud-init is running.)r   r   r   )status_fileresult_filer   r   r    
is_runningy  s    r   c                 C   s6   |t krtjS t| |rtjS |dkr,tjS tjS dS )z(Return the running status of cloud-init.r   N)r   r   r   r   r   r   r   )r   r   r3   latest_eventr   r   r    get_running_status~  s    
r   c                 C   s4   |  dd}|r0|d\}}}| dd}|S )zyGet the datasource from status.json.

    Return a lowercased non-prefixed version. So "DataSourceEc2" becomes "ec2"
    r8   r^   rW   )rn   	partitionlowerra   )	status_v1r8   Zds_r   r   r    get_datasource  s
    r   c                 C   s2   |  d}|r|S |  dr*d| d  S |S dS )zReturn a description of the current status.

    If we have a datasource, return that. If we're running in a particular
    stage, return that. Otherwise, return the boot_description.
    r8   ZstagezRunning in stage: N)rn   )r   boot_descriptionr8   r   r   r    get_description  s    

r   c                 C   s@   d}|   D ].}t|trt||dp*d|dp6d}q|S )z,Return the latest event time from status_v1.r   startZfinished)values
isinstancer   maxrn   )r   r   
stage_infor   r   r    get_latest_event  s    
r   c                 C   s   g }i }t |  D ]j\}}t|tr||dg  |di }| D ]0}||krjt|| ||< qL|| ||  qLq||fS )z>Return a list of errors and recoverable_errors from status_v1.r5   r6   )sortedro   r   r   extendrn   keysr   )r   r5   r6   Z_keyr   Zcurrent_recoverable_errorsZerr_typer   r   r    
get_errors  s$    
 
r   F)r|   r=   r>   c              
   C   s  t j}| pt } tj| jd}tj| jd}tt| |\}}i }tj	|rdt
t|di }t|}t||}	t|}
|
rtdt|
nd}t|\}}|rt j}n
|rt j}t||||
}|tjkrt rt|drtj}t j}d}	|d |d	d
 t||||	|||||	S )a  Return a dict with status, details and errors.

    @param paths: An initialized cloudinit.helpers.paths object.
    @param wait: If user has indicated to wait for cloud-init to complete.

    Values are obtained from parsing paths.run_dir/status.json.
    zstatus.jsonzresult.jsonr9   z%a, %d %b %Y %H:%M:%S %zr^   r~   z"Failed due to systemd unit failurezFailed due to systemd unit failure. Ensure all cloud-init services are enabled, and check 'systemctl' or 'journalctl' for more information.r8   N)r!   r%   r   r   r   re   r   r   CLOUDINIT_DISABLED_FILEr   r   r   rn   r   r   r   r   r   r   r#   r$   r   r   r   r   r   r   appendpopr0   )r|   r=   r2   r   r   r3   r   r   r8   r4   r   r7   r5   r6   r1   r   r   r    rw     sl    

  
   rw   c                  C   s   t  } ttd|   dS )z$Tool to report status of cloud-init.rE   N)rU   rx   exitr}   
parse_argsrS   r   r   r    main  s    r   __main__)N)NF)Cr   rP   enumrG   r   rx   copyr   timer   r   r   typingr   r   r   r	   r
   r   Z	cloudinitr   r   Zcloudinit.cmd.develr   Zcloudinit.distrosr   Zcloudinit.helpersr   Zcloudinit.utilr   r   r   r   uniqueEnumr   r!   r&   	frozensetr(   r)   r*   r+   r   r0   rp   r;   boolrD   rU   rY   rt   intr}   r   r   r   r   r   r   r   r   r   r   rw   r   r   r   r   r   r    <module>   sz    	
	
) 
E	*:    G
