o
    3'fF                     @   s\  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-dee. de/de.fddZ0d@ddZ1de#de$dee.e.f fddZ2d e,fd!d"Z3de4fd#d$Z5de/fd%d&Z6dee%e.f fd'd(Z7de/fd)d*Z8de/de/fd+d,Z9de/fd-d.Z:de#fd/d0Z;de.fd1d2Z<d3d4 Z=d5d6 Z>deeef fd7d8Z?	9dAd:ee de/de,fd;d<Z@d=d> ZAeBd?kr,eA  dS dS )BzGDefine '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running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.errordegraded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!   r3   F   s   
 r3   zextended_status: {extended_status}
boot_status_code: {boot_code}
{last_update}detail: {description}
errors:{errors}
recoverable_errors:{recoverable_errors}systemctl_argswaitreturnc                C   s@   	 zt  dg| j W S  t jy   |s td Y nw q)z-Query systemd with retries and return output.T	systemctl      ?)r   stdoutstripProcessExecutionErrorr   )r?   r@   r    r    r!   query_systemctlZ   s   rG   c                 C   sV   | s	t jddd} | jdtg d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)progr7   z--format)jsontabularyamlrK   z5Specify 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)actionrO   rP   z-wz--waitz'Block waiting on cloud-init to complete)argparseArgumentParseradd_argumentr>   parserr    r    r!   
get_parseri   s4   	
rX   r   	conditionc                 C   s^   |t jkrd|j d| j fS |t jkr)| tjtjfv r)| 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   rY   r    r    r!   translate_status   s   
	r\   detailsc           
   
   C   sj  t |j|j\}}|j|jj|||j|j|j|j	d|j
}dt|i|d< d|d< | jdkr| jr4dnd}|d }t| d	|  | jr|d
rTd|d
  d}nd}|d rcdd|d  nd}|d rydddd |d  D  nd}	ttj|d ||d |d |||	d dS dS | jdkrttj|dddd dS | jdkrtt| dS dS )zPrint status out to the CLI.)r;   r6   rH   extended_statusdetailr8   r9   r:   1schemas_schema_versionrK   
 rH   zstatus: r:   zlast_update: r8   
	- z []r9   c                 S   s.   g | ]\}}| d d dd |D  qS )z:
	- re   c                 S   s   g | ]}| d dqS )rc   rZ   )replace).0ir    r    r!   
<listcomp>   s    z+print_status.<locals>.<listcomp>.<listcomp>)join)rg   kvr    r    r!   ri      s    z print_status.<locals>.<listcomp>z {}r^   r6   r_   )r^   prefix	boot_coder7   r:   r8   r9   rJ      T),z: )indent	sort_keys
separatorsrL   N)r\   r4   r5   r;   r6   r[   r7   r8   r9   r:   r<   r   formatr@   printlonggetrj   itemsTABULAR_LONG_TMPLrJ   dumpsr   )
argsr]   rH   r^   details_dictrm   stater:   errors_outputrecoverable_errors_outputr    r    r!   print_status   sv   	


	
!
r   c                 C   s   t  }t||j}|jr8|jtjtjfv r8|jdkr%tj	
d tj	  t||j}td |jtjtjfv st|| |jtjkrEdS |jtjkrMdS dS )z4Handle calls to 'cloud-init status' as a subcommand.rK   .rC      r   )r   get_status_detailsr@   r4   r   r   r   rt   sysrD   writeflushr   r   r5   r"   r&   r'   )namer{   pathsr]   r    r    r!   handle_status_args   s,   



r   c                 C   s8   zt dg| d}W d|v S  tjy   d}Y d|v S w )z?Return whether cloud-init is disabled via environment variable.zshow-environmentr@   rd   cloud-init=disabled)rG   r   rF   )r@   envr    r    r!   _disabled_via_environment  s   r   c                 C   s  t   }t stj}d}||fS d|v rtj}d}||fS tj| r0tj	}d
| }||fS d|v r=tj}d}||fS dtjddv sNt rWt|d	rWtj}d
}||fS tjtj|jdrltj}d}||fS tjtj|jdrtj}d}||fS 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=disabledKERNEL_CMDLINErd   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)   r1   r0   ospathexistsr-   rt   r,   environrw   r   r.   rj   run_dirr+   r/   r2   )disable_filer   r@   cmdline_partsbootstatus_codereasonr    r    r!   get_bootstatus  sJ   
	
r   c                   C   s   t t jtvS N)r   r   r6   DISABLED_BOOT_CODESr    r    r    r!   is_cloud_init_enabled8  s   
r   c                 C   s   dD ]y}zt dd|g| d}W n  tjy/ } ztd|j tjd W Y d}~ dS d}~ww td	d
 | D }|d dsK|d dksK dS |d dkrj|d dkrXq|d dkrg|d dkrg dS  dS |d dksv|d dkry 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.serviceshowz5--property=ActiveState,UnitFileState,SubState,MainPIDr   z^Failed to get status from systemd. Cloud-init status may be inaccurate. Error from systemctl: )fileNFc                 S   s    g | ]}d d | dD qS )c                 S   s   g | ]}|  qS r    )rE   )rg   xr    r    r!   ri   Z  s    z-systemd_failed.<locals>.<listcomp>.<listcomp>=)r   )rg   rr    r    r!   ri   Z  s     z"systemd_failed.<locals>.<listcomp>UnitFileStater   staticTActiveStateactiveSubStateexitedr   MainPID0failed)	rG   r   rF   ru   stderrr   dict
splitlines
startswith)r@   servicerD   estatesr    r    r!   systemd_failed?  sH   
	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   s2   |t v rtjS t| |rtjS |dkrtjS tjS )z(Return the running status of cloud-init.r   )r   r   r   r   r   r   r   )r   r   r6   latest_eventr    r    r!   get_running_status~  s   
r   c                 C   s4   |  dd}|r|d\}}}| dd}|S )zyGet the datasource from status.json.

    Return a lowercased non-prefixed version. So "DataSourceEc2" becomes "ec2"
    r;   rd   rZ   )rw   	partitionlowerrf   )	status_v1r;   ds_r    r    r!   get_datasource  s
   r   c                 C   s.   |  d}|r	|S |  drd| d  S |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.
    r;   stagezRunning in stage: )rw   )r   boot_descriptionr;   r    r    r!   get_description  s   

r   c                 C   s@   d}|   D ]}t|trt||dpd|dpd}q|S )z,Return the latest event time from status_v1.r   startfinished)values
isinstancer   maxrw   )r   r   
stage_infor    r    r!   get_latest_event  s   
r   c                 C   s   g }i }t |  D ]5\}}t|tr?||dg  |di }| D ]}||vr5t|| ||< q&|| ||  q&q
||fS )z>Return a list of errors and recoverable_errors from status_v1.r8   r9   )sortedrx   r   r   extendrw   keysr   )r   r8   r9   _keyr   current_recoverable_errorserr_typer    r    r!   
get_errors  s$   

r   Fr   c              
   C   s  t j}| pt } tj| jd}tj| jd}tt| |\}}i }tj	|r2t
t|di }t|}t||}	t|}
|
rHtdt|
nd}t|\}}|rVt j}n|r[t j}t||||
}|tjkr|t r|t|dr|t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.jsonr<   z%a, %d %b %Y %H:%M:%S %zrd   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.r;   N)r"   r(   r   r   r   rj   r   r   CLOUDINIT_DISABLED_FILEr   r   r   rw   r   r   r   r   r   r   r&   r'   r   r   r   r   r   r   appendpopr3   )r   r@   r5   r   r   r6   r   r   r;   r7   r   r:   r8   r9   r4   r    r    r!   r     s`   



r   c                  C   s   t  } ttd|   dS )z$Tool to report status of cloud-init.rH   N)rX   r   exitr   
parse_argsrV   r    r    r!   main  s   r   __main__r   )NF)Cr   rS   enumrJ   r   r   copyr   timer   r   r   typingr   r   r   r	   r
   r   	cloudinitr   r   cloudinit.cmd.develr   cloudinit.distrosr   cloudinit.helpersr   cloudinit.utilr   r   r   r   uniqueEnumr   r"   r)   	frozensetr+   r,   r-   r.   r   r3   ry   r>   boolrG   rX   r\   r   intr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r    r    r!   <module>   s    	


(

E	*:

G

