o
    fg7                     @   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ZddlZddlZddl	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 ddlmZmZ ddlmZ dd	lmZmZmZ eej e!e"Z#G d
d deZ$e$dde$dde$ddgZ%e$dde$dde$dde$dde$dde$dde$dde$d d!e$d"d#e$d$d%e$d&d%e$d'd(gZ&	dcd)eej' d*ej'fd+d,Z(d-ee) d.ej*d/e)d*ee) fd0d1Z+d-ee) d.ej*d/e)d*dfd2d3Z,d4ej*d5ej*d6e-d*dfd7d8Z.d9ej*d6e-d*dfd:d;Z/d9ej*d*dfd<d=Z0d9ej*d6e-d*dfd>d?Z1d@ee)ef d*eej* fdAdBZ2e*dCfdDej*d*eej* fdEdFZ3dGej*d*eej* fdHdIZ4dJej*d*eej* fdKdLZ5d9ej*d@ee)ef dJej*dGej*d6e-d*dfdMdNZ6e*dOe*dPdQfdRe)d@ee)ef dJej*dGej*d6e-d*dfdSdTZ7dUe8d*dfdVdWZ9		Q	XdddRe)dUe8dYe-dZe-d*df
d[d\Z:d]e)d^ej;d*e8fd_d`Z<e"dakre=e<dbe( >  dS dS )ezGDefine 'collect-logs' utility and handler to include in cloud-init cmd.    N)datetimetimezone)AnyDictIteratorList
NamedTupleOptionalcast)log)Init)ProcessExecutionErrorsubp)tempdir)copyget_config_logfiles
write_filec                   @   s   e Zd ZU eed< eed< dS )
ApportFilepathlabelN)__name__
__module____qualname__str__annotations__ r   r   :/usr/lib/python3/dist-packages/cloudinit/cmd/devel/logs.pyr      s   
 r   z(/var/log/installer/autoinstall-user-dataAutoInstallUserDataz/autoinstall.yamlAutoInstallYAMLz'/etc/cloud/cloud.cfg.d/99-installer.cfgInstallerCloudCfgz//var/log/installer/ubuntu_desktop_installer.logUdiLogz-/var/log/installer/subiquity-server-debug.logSubiquityServerDebugz-/var/log/installer/subiquity-client-debug.logSubiquityClientDebugz%/var/log/installer/curtin-install.log	CurtinLogz0/var/log/installer/subiquity-curtin-install.confCurtinInstallConfigz8/var/log/installer/curtin-install/subiquity-initial.confCurtinConfigInitialz:/var/log/installer/curtin-install/subiquity-curthooks.confCurtinConfigCurtHooksz8/var/log/installer/curtin-install/subiquity-extract.confCurtinConfigExtractz=/var/log/installer/curtin-install/subiquity-partitioning.confCurtinConfigPartitioningz(/var/log/installer/curtin-error-logs.tarCurtinErrorz$/var/log/installer/curtin-errors.tarz(/var/log/installer/block/probe-data.json	ProbeDataparserreturnc                 C   sh   | s	t jddd} | jdddddd	d
 | jddddd | jddddddd | jdddddd | S )a2  Build or extend and arg parser for collect-logs utility.

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

    @returns: ArgumentParser with proper argument configuration.
    zcollect-logsz)Collect and tar all cloud-init debug info)progdescriptionz	--verbosez-vcountr   	verbosityzBe more verbose.)actiondefaultdesthelpz	--tarfilez-tzcloud-init.tar.gzzOThe tarfile to create containing all collected logs. Default: cloud-init.tar.gz)r2   r4   z--include-userdataz-uF
store_trueuserdataz?DEPRECATED: This is default behavior and this flag does nothing)r2   r1   r3   r4   z--redact-sensitivez-rzRedact potentially sensitive data from logs. Sensitive data may include passwords or keys in user data and root read-only files.)r2   r1   r4   )argparseArgumentParseradd_argument)r+   r   r   r   
get_parserO   sF   	
r:   cmd	file_pathmsgc              
   C   s   |j jddd zt| j}W n" ty1 } zt|t| td| d}W Y d}~|S d}~ww t|| td||j	 |S )zCHelper which runs a command and writes output or error to filename.Tparentsexist_okcollecting %s failed.Ncollected %s to file '%s')
parentmkdirr   stdoutr   r   r   LOGdebugstem)r;   r<   r=   outputer   r   r   _write_command_output_to_file   s   
rK   c              
   C   s   |j jddd z|d}tj| ||d W d   n1 s!w   Y  W n  tyG } zt|t| t	d| W Y d}~dS d}~ww t	d||j
 dS )zHelper which runs a command and writes output or error to filename.

    `subprocess.call` is invoked directly here to stream output to the file.
    Otherwise memory usage can be high for large outputs.
    Tr>   w)rE   stderrNrA   rB   )rC   rD   open
subprocesscallOSErrorr   r   rF   rG   rH   )r;   r<   r=   frJ   r   r   r   _stream_command_output_to_file   s   rS   r   out_dirinclude_sensitivec                 C   sd   |   r*|s|  jtj@ r"|jddd t| | td|  dS td|  dS td|  dS )z-Collect a file into what will be the tarball.Tr>   zcollected file: %sz#sensitive file %s was not collectedzfile %s did not existN)	is_filestatst_modeS_IROTHrD   r   rF   rG   trace)r   rT   rU   r   r   r   _collect_file   s   
r[   log_dirc                 C   s|   t D ]}t| |jdd j}tt|j|dd q|r:tD ]}t| |jdd j}tt|j|dd q dS dS )z'Obtain subiquity logs and config files.   NT)rU   )INSTALLER_APPORT_FILESpathlibPathr   rC   r[    INSTALLER_APPORT_SENSITIVE_FILES)r\   rU   src_filedestination_dirr   r   r   _collect_installer_logs   s"   

rd   c                 C   s@   t ddg| d dd}t g d| d dd}|s|pd	}d
S d
S )z8Include cloud-init version and dpkg version in the logs.
cloud-initz	--versionversionzcloud-init --versionr;   r<   r=   )z
dpkg-queryz--showz-f=${Version}
re   zdpkg-versionzdpkg versionznot-availableN)rK   )r\   rf   dpkg_verr   r   r   _collect_version_info   s   ri   c                 C   sL   |rt dg| d dd t g d| d dd t g dt| d	d
d dS )z0Include dmesg and journalctl output in the logs.dmesgz	dmesg.txtzdmesg outputrg   )
journalctlz--boot=0-oshort-precisezjournal.txtzsystemd journal of current boot)rk   z	--boot=-1rl   rm   zjournal-previous.txtz systemd journal of previous bootN)rS   r_   r`   )r\   rU   r   r   r   _collect_system_logs   s    

rn   log_cfgc                 c   s     t | D ]}t|V  qdS )z7Get paths for cloud-init.log and cloud-init-output.log.N)r   r_   r`   )ro   r   r   r   r   _get_cloudinit_logs   s   rp   z
/etc/cloudetc_cloud_dirc                 #   s6    | d | d dg  fdd|  dD E dH  dS )zGet paths for all files in /etc/cloud.

    Excludes:
      /etc/cloud/keys because it may contain non-useful sensitive data.
      /etc/cloud/templates because we already know its contents
    keys	templatesz99-installer.cfgc                 3   s(    | ]}|j  vr|j vr|V  qd S N)namerC   ).0r   ignorer   r   	<genexpr>  s    z!_get_etc_cloud.<locals>.<genexpr>z**/*Nglob)rq   r   rw   r   _get_etc_cloud   s   

r|   	cloud_dirc              	   C   s:   t | d| d| ddd | dD | dS )zkGet paths for files in /var/lib/cloud.

    Skip user-provided scripts, semaphores, and old instances.
    zdata/*z
handlers/*zseed/*c                 s   s    | ]	}|  r|V  qd S rt   )rV   rv   pr   r   r   ry     s    z%_get_var_lib_cloud.<locals>.<genexpr>z
instance/*zinstance/handlers)	itertoolschainr{   r}   r   r   r   _get_var_lib_cloud  s   r   run_dirc                 C   s   dd |  dD S )zGet all paths under /run/cloud-init except for hook-hotplug-cmd.

    Note that this only globs the top-level directory as there are currently
    no relevant files within subdirectories.
    c                 s   s    | ]
}|j d kr|V  qdS )zhook-hotplug-cmdN)ru   r~   r   r   r   ry   *  s    z_get_run_dir.<locals>.<genexpr>*rz   r   r   r   r   _get_run_dir$  s   r   c                 C   s   t |  t| | t| | t|D ]}t|| t|jd d qt	
t t|dt|dD ]}t|| t|jd | q2dS )z8Collect all cloud-init logs into the provided directory./Tr   r   N)ri   rn   rd   rp   r[   r_   r`   rC   relative_tor   r   r|   r   r   )r\   ro   r   r}   rU   logfiler   r   r   _collect_logs_into_tmp_dir-  s(   

r   z/run/cloud-initz/var/lib/cloudTtarfilec                 C   s   t j| } ttj d}t	|d*}t
||}t|||||d tdd| d|t|| ddg W d	   n1 sCw   Y  td
|  d	S )a  Collect all cloud-init logs and tar them up into the provided tarfile.

    :param tarfile: The path of the tar-gzipped file to create.
    :param log_cfg: The cloud-init base configuration containing logging cfg.
    :param run_dir: The path to the cloud-init run directory.
    :param cloud_dir: The path to the cloud-init cloud directory.
    :param include_sensitive: Boolean, true means include sensitive data.
    zcloud-init-logs-%Y-%m-%d)dir)r\   ro   r   r}   rU   tarczfz-Cr    NzWrote %s)osr   abspathr   nowr   utcdatestrftimer   r_   r`   r   r   r   replacerF   info)r   ro   r   r}   rU   dir_nametmp_dirr\   r   r   r   collect_logsN  s.   r   r0   c                 C   s^   t   | dkrtj}n| dkrtj}nt j}t| t }|	t
d t| dS )zSet up the logger for CLI use.

    The verbosity controls which level gets printed to stderr. By default,
    DEBUG and TRACE are hidden.
    r   r]   z%(message)sN)r   reset_loggingloggingINFODEBUGTRACErF   setLevelStreamHandlersetFormatter	Formatter
addHandler)r0   levelhandlerr   r   r   _setup_loggerw  s   
r   Fredact_sensitiveinclude_userdatac                 C   s|   t | t dkrtd|rtd tg d}|  t| |j	t
|jjt
|jj| d |s<td dS dS )z:Handle calls to 'cloud-init collect-logs' as a subcommand.r   z!This command must be run as root.z;The --include-userdata flag is deprecated and does nothing.)ds_deps)r   ro   r   r}   rU   zWARNING:
Sensitive data may have been included in the collected logs.
Please review the contents of the tarball before sharing or
rerun with --redact-sensitive to redact sensitive data.N)r   r   getuidRuntimeErrorrF   warningr   read_cfgr   cfgr_   r`   pathsr   r}   )r   r0   r   r   initr   r   r   collect_logs_cli  s*   
r   _nameargsc              
   C   s^   t   }zt|j|j|j|jd W dS  ty. } zt|t	j
d W Y d}~dS d}~ww )z}Handle the CLI interface to the module.

    Parse CLI args, redirect all exceptions to stderr, and return an exit code.
    )r0   r   r   r   r   )fileNr]   )r:   
parse_argsr   r0   r   r   r6   	ExceptionprintsysrM   )r   r   rJ   r   r   r   handle_collect_logs_args  s   
r   __main__r   rt   )r   TF)?__doc__r7   r   r   r   r_   rW   rO   r   r   r   typingr   r   r   r   r   r	   r
   	cloudinitr   cloudinit.stagesr   cloudinit.subpr   r   cloudinit.temp_utilsr   cloudinit.utilr   r   r   CustomLoggerType	getLoggerr   rF   r   ra   r^   r8   r:   r   r`   rK   rS   boolr[   rd   ri   rn   rp   r|   r   r   r   r   intr   r   	Namespacer   exitr   r   r   r   r   <module>   sJ  $	&
9






	
	

$

)
!
