o
    w7e5                  
   @   s  U d 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	 ddl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mZ dd
lmZ dZdddeegeedededgdgdZeed< eeZ dddi i ddgddZddgdddgdddgddZe	eZe d Z!e d!Z"d"efd#d$Z#d<d%d&Z$d=d'd(Z%d)e&d"ed*e&fd+d,Z'd-d. Z(d>d/d0Z)G d1d2 d2Z*d?d3d4Z+d5ed*dfd6d7Z,d8e-d)ed5ed9e.d*df
d:d;Z/dS )@z-Rsyslog: Configure system logging via rsyslog    N)dedent)log)subputil)Cloud)Config)
MetaSchemaget_meta_doc)ALL_DISTROSDistro)PER_INSTANCEam  This module configures remote system logging using rsyslog.

Configuration for remote servers can be specified in ``configs``, but for
convenience it can be specified as key value pairs in ``remotes``.

This module can install rsyslog if not already present on the system using the
``install_rsyslog``, ``packages``, and ``check_exe`` options. Installation
may not work on systems where this module runs before networking is up.

.. note::
    On BSD cloud-init will attempt to disable and stop the base system syslogd.
    This may fail on a first run.
    We recommend creating images with ``service syslogd disable``.

cc_rsyslogRsyslogz$Configure system logging via rsyslogz            rsyslog:
                remotes:
                    maas: 192.168.1.1
                    juju: 10.0.4.1
                service_reload_command: auto
            a7              rsyslog:
                config_dir: /opt/etc/rsyslog.d
                config_filename: 99-late-cloud-config.conf
                configs:
                    - "*.* @@192.158.1.1"
                    - content: "*.*   @@192.0.2.1:10514"
                      filename: 01-example.conf
                    - content: |
                        *.*   @@syslogd.example.com
                remotes:
                    maas: 192.168.1.1
                    juju: 10.0.4.1
                service_reload_command: [your, syslog, restart, command]
            a              # default (no) configuration with package installation on FreeBSD
            rsyslog:
                config_dir: /usr/local/etc/rsyslog.d
                check_exe: "rsyslogd"
                packages: ["rsyslogd"]
                install_rsyslog: True
            rsyslog)idnametitledescriptiondistros	frequencyexamplesactivate_by_schema_keysmetaz/etc/rsyslog.dz20-cloud-config.confautorsyslogdF)
config_dirconfig_filenameservice_reload_commandremotesconfigs	check_exepackagesinstall_rsyslogz/usr/local/etc/rsyslog.d)r   r!   zsysutils/rsyslogz/usr/pkg/etc/rsyslog.d)freebsdopenbsdnetbsdz[ ]*[#]+[ ]*z_^(?P<proto>[@]{0,2})(([\[](?P<bracket_addr>[^\]]*)[\]])|(?P<addr>[^:]*))([:](?P<port>[0-9]+))?$distroc                 C   s4   t }tt}| j|v rtj||| j gdd}|S )zConstruct a distro-specific rsyslog config dictionary by merging
       distro specific changes into base config.

    @param distro: String providing the distro class name.
    @returns: Dict of distro configurations for ntp clients.
    T)reverse)DISTRO_OVERRIDEScopyRSYSLOG_CONFIGosfamilyr   mergemanydictr   )r&   dcfgcfg r/   =/usr/lib/python3/dist-packages/cloudinit/config/cc_rsyslog.pydistro_default_rsyslog_config   s
   

r1   c                 C   s(   t |rdS |du rdg}| | dS )ai  Install rsyslog package if not already installed.

    @param install_func: function.  This parameter is invoked with the contents
    of the packages parameter.
    @param packages: list.  This parameter defaults to ['rsyslog'].
    @param check_exe: string.  The name of a binary that indicates the package
    the specified package is already installed.
    Nr   )r   which)install_funcr!   r    r/   r/   r0   r"      s
   
	r"   c                 C   s.   |dkr|  dd}| d|S tj|ddS )Nr   rsyslog_svcnamer   z
try-reloadT)capture)
get_optionmanage_servicer   )r&   commandservicer/   r/   r0   reload_syslog   s   r:   r.   returnc              
   C   s"  |  di }t|}t|  dtr4tjddd d|  di}d| v r*| d |d< d| v r4| d |d	< dg tfd	|d	 tfd|d tfd
|d
 tfd|d ttffd|d tfd|d tfd|d tff}|D ]&\}}}||vrv|||< qht|| |st	d| d| dt
||  qh|S )zReturn an updated config.

    Support converting the old top level format into new format.
    Raise a `ValueError` if some top level entry has an incorrect type.
    r   z)The rsyslog key with value of type 'list'z22.2)
deprecateddeprecated_versionr   rsyslog_filenamer   rsyslog_dirr   r   r   r    r!   r"   zInvalid type for key `z`. Expected type(s): z. Current type: )getr1   
isinstancelistr   	deprecatestrdictbool
ValueErrortype)r.   r&   mycfgdistro_configfillupkeydefaultvtypesr/   r/   r0   load_config   sF   

rO   c           
   	   C   s   g }t | D ]m\}}t|tr'd|vrtd|d  q|d }|d|}n|}|}| }|s:td|d  qtj	||}d}||vrNd}|
| zd}	|d	sXd	}	tj|||	 |d
 W q tys   ttd| Y qw |S )Ncontentz%No 'content' entry in config entry %s   filenamezEntry %s has an empty filenameabwb 
)omodezFailed to write to %s)	enumeraterA   rE   LOGwarningr@   stripospathjoinappendendswithr   
write_file	Exceptionlogexc)
r   	def_fnamecfg_dirfilescur_posentrP   rR   rW   endlr/   r/   r0   apply_rsyslog_changes   s<   


rj   c                 C   s  zt | \}}| }W n ty   | d }}Y nw |  }d }t|dkr-|}nt|dkr8|\}}ntd| t|}|sKtd| |d}|dpY|d}|d}	|d	ro|	d
sotd| |ru|su|}t
|||||	d}
|
  |
S )NrQ      zline had multiple spaces: %szInvalid host specification '%s'protoaddrbracket_addrport[]z"host spec had invalid brackets: %sr   matchrl   rm   ro   )
COMMENT_REsplitr[   rG   lenHOST_PORT_RErs   group
startswithr`   SyslogRemotesLinevalidate)liner   datacommenttoksrs   	host_portrl   rm   ro   tr/   r/   r0   parse_remotes_line   s8   




r   c                   @   s0   e Zd Z	d
ddZdd Zdd Zdd	 ZdS )rz   Nc                 C   s^   |sd}|| _ || _|sd}|dkrd}n|dkrd}|| _|| _|r*t|| _d S d | _d S )Nz*.*udp@@@tcp)r   rs   rl   rm   intro   )selfr   rs   rl   rm   ro   r/   r/   r0   __init__&  s   
zSyslogRemotesLine.__init__c              
   C   sP   | j rzt| j  W n ty } ztd| j  |d }~ww | js&tdd S )Nzport '%s' is not an integerzaddress is required)ro   r   rG   rm   )r   er/   r/   r0   r{   ;  s   zSyslogRemotesLine.validatec                 C   s   d| j | j| j| j| jf S )Nz.[name=%s match=%s proto=%s address=%s port=%s]rr   )r   r/   r/   r0   __repr__G  s   zSyslogRemotesLine.__repr__c                 C   s   | j d }| jdkr|d7 }n	| jdkr|d7 }d| jv r'|d| j d 7 }n|| j7 }| jr6|d	| j 7 }| jr@|d
| j 7 }|S )N r   r   r   r   :rp   rq   z:%sz # %s)rs   rl   rm   ro   r   )r   bufr/   r/   r0   __str__P  s   





zSyslogRemotesLine.__str__)NNNNN)__name__
__module____qualname__r   r{   r   r   r/   r/   r/   r0   rz   %  s    
	rz   c                 C   s   | sd S g }|d ur| | |  D ].\}}|sqz| tt||d W q tyA } ztd||| W Y d }~qd }~ww |d urK| | d|d S )N)r   z!failed loading remote %s: %s [%s]rV   )r_   itemsrD   r   rG   rY   rZ   r^   )r   headerfooterlinesr   r|   r   r/   r/   r0   remotes_to_rsyslog_cfgd  s"   

r   cloudc                 C   s   z	| j dd W n tjy   Y dS w | j dd | j   ttj | j dd td W d   dS 1 s?w   Y  dS )z
    This helper function bundles the necessary steps to disable BSD base syslog
    ``rc(8)`` reads its configuration on start, so after disabling syslogd, we
    need to tell rc to reload its config
    enabledsyslogdNdisableonestopzOsyslogd is running before cloud-init! Please report this as bug to the porters!)	r&   r7   r   ProcessExecutionErrorreload_init
contextlibsuppressrY   error)r   r/   r/   r0    disable_and_stop_bsd_base_syslogv  s   
"r   r   argsc           
   
   C   sT  d|vrt d|  d S t||j}|d }|d r&|t|d ddd |jdd}|d	 d
u r@t|jj|d |d d t	
 rO|jd| t| |d sZt d d S t|d |d |d d}|spt d d S zt|j|d d}W n tjy }	 zd}t dt|	 W Y d }	~	nd }	~	ww |r|  t d| | d S d S )Nr   z;Skipping module named %s, no 'rsyslog' key in configurationr   r   z# begin remotesz# end remotes)r   r   r4   r"   Tr!   r    )r!   r    enablez.Empty config rsyslog['configs'], nothing to dor   r   )r   rd   re   z0restart of syslog not necessary, no changes mader   )r8   FzFailed to reload syslog %sz%s configured %s files)rY   debugrO   r&   r_   r   r6   r"   install_packagesr   is_BSDr7   r   rj   r:   r   r   rZ   rD   cycle_logging)
r   r.   r   r   rI   r   r9   changes	restartedr   r/   r/   r0   handle  sb   



r   )Nr   )r   )N)NN)0__doc__r   r)   r\   retextwrapr   	cloudinitr   loggingr   r   cloudinit.cloudr   cloudinit.configr   cloudinit.config.schemar   r	   cloudinit.distrosr
   r   cloudinit.settingsr   MODULE_DESCRIPTIONr   __annotations__r*   r(   	getLoggerr   rY   compilert   rw   r1   r"   r:   rE   rO   rj   r   rz   r   r   rD   rB   r   r/   r/   r/   r0   <module>   s   
	&0



/
)&
?"