o
    w7eS                     @   s  U d 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	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 eeZeZd
ZdZg dZdddgdddddedgdddddedgddddddg ddddddg dddddZdddd
g ddd d!did!did"dddd#idd$diid
ddd%d&dgddd'd(d)d*gd*d+d,d-d!did.d/d0d1d*i id!did
ddd2did3d!did
ddd2d.id3d!didd
d#d.d/d0d3d!did!did"d!did
ddd2d.id3dd$diid4Zd5D ]Zed6 ee< qd7D ]	Zed8 ee< q
d9d:d;ed<eed=ed>gedgd?Z ee!d@< ee Z e"g dAZ#dBdC Z$dDdE Z%dWdFdGZ&dXdHdIZ'dJdK Z(								dYdLdMZ)dNdO Z*dPe+dQedRedSe,dTdf
dUdVZ-dS )ZzNTP: enable and configure ntp    N)dedent)log)subp
temp_utils	templater
type_utilsutil)Cloud)Config)
MetaSchemaget_meta_doc)PER_INSTANCEz/etc/ntp.conf   )	almalinuxalpinecentos
cloudlinuxcosdebian	eurolinuxfedorafreebsdmarinermiraclelinuxopenbsd	openeulerOpenCloudOSopenmandrivaopensuseopensuse-microosopensuse-tumbleweedopensuse-leapphotonrhelrockysle_hpc	sle-microsles	TencentOSubuntu	virtuozzochronydz/etc/chrony.confchronyzchrony.conf.{distro})	check_execonfpathpackagesservice_nametemplate_nametemplatentpdntpzntp.conf.{distro}ntpdatez/etc/ntpd.confzntpd.conf.{distro}z/lib/systemd/systemd-timesyncdz-/etc/systemd/timesyncd.conf.d/cloud-init.confsystemd-timesyncdztimesyncd.conf)r,   r4   r5   openntpdr6   z/etc/chrony/chrony.conf)r.   r0   )r.   r/   r0   )r,   r4   r0   )r4   r,   )r0   r.   r.   )r.   r0   r1   z/usr/local/etc/chrony.conf)r.   r/   r0   r1   z/usr/local/sbin/ntpdz/usr/local/etc/ntp.confr7   zntpd.conf.openbsd)r-   r.   r/   r0   r1   )r4   r,   r7   z"/usr/lib/systemd/systemd-timesyncdz/etc/systemd/timesyncd.conf)r-   r.   )r,   r6   r-   )r,   r4   r6   )r   r   r   r   r   r   r   r   r   r"   r#   r'   r)   )r   r    r!   r   )r%   r&   r'   cc_ntpNTPzenable and configure ntpaD          Handle ntp configuration. If ntp is not installed on the system and
        ntp configuration is specified, ntp will be installed. If there is a
        default ntp config file in the image or one is present in the
        distro's ntp package, it will be copied to a file with ``.dist``
        appended to the filename before any changes are made. A list of ntp
        pools and ntp servers can be provided under the ``ntp`` config key.
        If no ntp ``servers`` or ``pools`` are provided, 4 pools will be used
        in the format ``{0-3}.{distro}.pool.ntp.org``.z        # Override ntp with chrony configuration on Ubuntu
        ntp:
          enabled: true
          ntp_client: chrony  # Uses cloud-init default chrony configuration
        aY          # Provide a custom ntp client configuration
        ntp:
          enabled: true
          ntp_client: myntpclient
          config:
             confpath: /etc/myntpclient/myntpclient.conf
             check_exe: myntpclientd
             packages:
               - myntpclient
             service_name: myntpclient
             template: |
                 ## template:jinja
                 # My NTP Client config
                 {% if pools -%}# pools{% endif %}
                 {% for pool in pools -%}
                 pool {{pool}} iburst
                 {% endfor %}
                 {%- if servers %}# servers
                 {% endif %}
                 {% for server in servers -%}
                 server {{server}} iburst
                 {% endfor %}
                 {% if peers -%}# peers{% endif %}
                 {% for peer in peers -%}
                 peer {{peer}}
                 {% endfor %}
                 {% if allow -%}# allow{% endif %}
                 {% for cidr in allow -%}
                 allow {{cidr}}
                 {% endfor %}
          pools: [0.int.pool.ntp.org, 1.int.pool.ntp.org, ntp.myorg.org]
          servers:
            - ntp.server.local
            - ntp.ubuntu.com
            - 192.168.23.2
          allow:
            - 192.168.23.0/32
          peers:
            - km001
            - km002)idnametitledescriptiondistrosexamples	frequencyactivate_by_schema_keysmeta)r-   r.   r/   r0   c                 C   s0   t }tt}| |v rtj|||  gdd}|S )zConstruct a distro-specific ntp client 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_CLIENT_CONFIGcopyNTP_CLIENT_CONFIGr   mergemanydict)distrodcfgcfg rL   9/usr/lib/python3/dist-packages/cloudinit/config/cc_ntp.pydistro_ntp_client_configs<  s
   
rN   c                 C   s   t |j}| r| dkrtd|  || i S |dd}i }|dkrT|jD ]}||}t|dr?td| |} nq&|sR|jd }td| ||}|S td| ||i }|S )	a  Determine which ntp client is to be used, consulting the distro
       for its preference.

    @param ntp_client: String name of the ntp client to use.
    @param distro: Distro class instance.
    @returns: Dict of the selected ntp client or {} if none selected.
    autoz4Selected NTP client "%s" via user-data configuration
ntp_clientr-   z+Selected NTP client "%s", already installedr   z<Selected distro preferred NTP client "%s", not yet installedz1Selected NTP client "%s" via distro system config)	rN   r;   LOGdebugget
get_optionpreferred_ntp_clientsr   which)rP   rI   
distro_cfgdistro_ntp_client	clientcfgclientrK   rL   rL   rM   select_ntp_clientJ  s@   





r[   c                 C   s(   t |rdS |du rdg}| | dS )ah  Install ntp client 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 ['ntp'].
    @param check_exe: string.  The name of a binary that indicates the package
    the specified package is already installed.
    Nr4   )r   rV   )install_funcr/   r-   rL   rL   rM   install_ntp_client|  s
   
	r]   c                 C   s$   t j| rt| | d  dS dS )zRename any existing ntp client config file

    @param confpath: string. Specify a path to an existing ntp client
    configuration file.
    z.distN)ospathexistsr   renamer.   rL   rL   rM   rename_ntp_conf  s   rc   c                 C   sj   g }| }| dkrd}n
| dks| dkrd}t dtD ]}|ddd	 t|g|g d
g D  q|S )zGenerate a list of server names to populate an ntp client configuration
    file.

    @param distro: string.  Specify the distro name
    @returns: list: A list of strings representing ntp servers for this distro.
    r'   r   r   r    r   .c                 S   s   g | ]}|r|qS rL   rL   ).0nrL   rL   rM   
<listcomp>  s    z)generate_server_names.<locals>.<listcomp>zpool.ntp.org)rangeNR_POOL_SERVERSappendjoinstr)rI   namespool_distroxrL   rL   rM   generate_server_names  s   rq   c	                 C   s$  |sg }|sg }|sg }|sg }t |dkr"t |dkr"| dkr"dS t |dkr>| dkr>|dkr>t| }tdd| nt |dkrWt |dkrWt| }tdd| |s]td	|se|setd
||||d}	|rtjddd}
|
d }tj	||d t
|||	 |rt| dS dS )a  Render a ntp client configuration for the specified client.

    @param distro_name: string.  The distro class name.
    @param service_name: string. The name of the NTP client service.
    @param servers: A list of strings specifying ntp servers. Defaults to empty
    list.
    @param pools: A list of strings specifying ntp pools. Defaults to empty
    list.
    @param allow: A list of strings specifying a network/CIDR. Defaults to
    empty list.
    @param peers: A list nodes that should peer with each other. Defaults to
    empty list.
    @param path: A string to specify where to write the rendered template.
    @param template_fn: A string to specify the template source file.
    @param template: A string specifying the contents of the template. This
    content will be written to a temporary file before being used to render
    the configuration file.

    @raises: ValueError when path is None.
    @raises: ValueError when template_fn is None and template is None.
    r   r   Nr   r3   z%Adding distro default ntp servers: %s,z*Adding distro default ntp pool servers: %sz Invalid value for path parameterz$Not template_fn or template provided)serverspoolsallowpeersztemplate_name-z.tmpl)prefixsuffix   )content)lenrq   rQ   rR   rl   
ValueErrorr   mkstempr   
write_filer   render_to_filedel_file)distro_namer0   rs   rt   ru   rv   r_   template_fnr2   paramstfilerL   rL   rM   write_ntp_config_template  sJ     
r   c                 C   sB  g }t t|  }|rdt|}|dj|d nt| 	d| 	dgs/|d t| 
 D ]\\}}d| }|dkrUt|t|tgsT|d	j||d
 q5|dkrit|tsh|dj||d
 q5|dv r|du rrq5t|ts|dj||d
 q5t|ts|dj||d
 q5|rtdjd|ddS )aO  Validate user-provided ntp:config option values.

    This function supplements flexible jsonschema validation with specific
    value checks to aid in triage of invalid user-provided configuration.

    @param ntp_config: Dictionary of configuration value under 'ntp'.

    @raises: ValueError describing invalid values provided.
    z, z(Missing required ntp:config keys: {keys})keysr2   r1   zJEither ntp:config:template or ntp:config:template_name values are requiredzntp:config:r.   z6Expected a config file path {keypath}. Found ({value}))keypathvaluer/   zHExpected a list of required package names for {keypath}. Found ({value}))r2   r1   Nz5Expected a string type for {keypath}. Found ({value})z$Invalid ntp configuration:\n{errors}
)errors)REQUIRED_NTP_CONFIG_KEYS
differencesetr   rl   sortedrk   formatanyrS   itemsall
isinstancerm   listr|   )
ntp_configr   missingr   keyr   r   rL   rL   rM   supplemental_schema_validation  sn   




r   r;   rK   cloudargsreturnc                 C   s  d|vrt d|  dS |d }|du ri }t|ts&tdjt|d|dd}t	
|r9t d|  dS t|d	|j}t	j||d
i gdd}t| t|dd d}|ds|dd|jj}||}|sd|d }	t|	t d|d t d|dg  t d|dg  t d|dg  t d|dg  t|jj|d|dg |dg |dg |dg |d||dd	 t|jj|d |d d t	 rH|dd kr&z	|jd!d  W n tjy   t d" Y nw z	|jd#d  W n tjy%   t d$ Y nw z|jd%|d W n tjyG }
 zt d&|
  d}
~
ww z|jd'|d W dS  tjyj }
 zt d(|
  d}
~
ww ))zEnable and configure ntp.r4   z8Skipping module named %s, not present or disabled by cfgNzL'ntp' key existed in config, but not a dictionary type, is a {_type} instead)_typeenabledTz)Skipping module named %s, disabled by cfgrP   configrC   r.   rb   r2   r1   z{distro}z#No template found, not rendering %szservice_name: %sr0   zservers: %srs   z	pools: %srt   z	allow: %sru   z	peers: %srv   )r0   rs   rt   ru   rv   r_   r   r2   r/   r-   )r/   r-   r3   stopz Failed to stop base ntpd servicedisablez#Failed to disable base ntpd serviceenablez Failed to enable ntp service: %sreloadz&Failed to reload/start ntp service: %s)rQ   rR   r   dictRuntimeErrorr   r   obj_namerS   r   is_falser[   rI   rH   r   rc   replacer;   get_template_filenamer   r]   install_packagesis_BSDmanage_servicer   ProcessExecutionErrorwarning	exception)r;   rK   r   r   ntp_cfgr   ntp_client_configr   r1   msgerL   rL   rM   handleB  s   













r   )Nr3   )N)NNNNNNNN).__doc__rF   r^   textwrapr   	cloudinitr   loggingr   r   r   r   r   cloudinit.cloudr	   cloudinit.configr
   cloudinit.config.schemar   r   cloudinit.settingsr   	getLogger__name__rQ   r@   NTP_CONFrj   r>   rG   rE   rI   rB   __annotations__	frozensetr   rN   r[   r]   rc   rq   r   r   rm   r   r   rL   rL   rL   rM   <module>   sf  
!				/	

|	5H
2


Q"=