U
    AdN                     @   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 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dddddddddddddddddddd d!d"d#d$d%d&d'd(gZd)d*d+gd+d,dd-d.ed/gd/d0dd-d1ed1gd1d0dd-d.d2g d.d3dd-d4d5g d6d7dd-d8Zd9d)d:dg d.d;d<d=d.id=d)id>d+d)d9d?id+d@d9iidd.d0dAdBd+gd)d,dCdDdEdFgdFdGdHdId=d)idJdKdLdMdFi id=d)idd.d:dNd4idOd=d)idd.d:dNdJidOd=d)id.dd?dJdKdLdOd=d.id=d)id>d=d)idd.d:dNdJidOd+d@d9iidPZdQD ]Z ed ee < q>dRD ]Z ed% ee < qVdSdTdUedVeedWedXged/gdYZ!ee"dZ< ee!Z e#dNd@d[d=gZ$d\d] Z%d^d_ Z&dmd`daZ'dndbdcZ(ddde Z)dodfdgZ*dhdi Z+e,eeee-ddjdkdlZ.dS )pzNTP: enable and configure ntp    N)Logger)dedent)log)subp
temp_utils	templater
type_utilsutil)Cloud)Config)
MetaSchemaget_meta_doc)PER_INSTANCEz/etc/ntp.conf   Z	almalinuxalpinecentosZ
cloudlinuxcosdebian	eurolinuxZfedorafreebsdmarinerZmiraclelinuxopenbsdZ	openEulerZOpenCloudOSopenmandrivaopensuseopensuse-microosopensuse-tumbleweedopensuse-leapphotonrhelZrockysle_hpc	sle-microslesZ	TencentOSubuntuZ	virtuozzoZ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#   r+   r,   openntpdr-   z/etc/chrony/chrony.conf)r%   r'   )r%   r&   r'   )r#   r+   r'   )r+   r#   )r'   r%   r%   )r%   r'   r(   z/usr/local/etc/chrony.conf)r%   r&   r'   r(   z/usr/local/sbin/ntpdz/usr/local/etc/ntp.confr.   zntpd.conf.openbsd)r$   r%   r&   r'   r(   )r+   r#   r.   z"/usr/lib/systemd/systemd-timesyncdz/etc/systemd/timesyncd.conf)r$   r%   )r#   r-   r$   )r#   r+   r-   )r   r   r   r   r   r   r   r   r   r   r   r!   r"   )r   r   r   )r   r    Zcc_ntpZ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
        a          # 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 %}
          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)idnametitleZdescriptiondistrosZexamples	frequencyZactivate_by_schema_keysmetar&   c                 C   s0   t }tt}| |k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)distroZdcfgcfg r=   9/usr/lib/python3/dist-packages/cloudinit/config/cc_ntp.pydistro_ntp_client_configs0  s
    
r?   c                 C   s   t |j}| r.| dkr.td|  || i S |dd}i }|dkr|jD ]2}||}t|drLtd| |} qqL|s|jd }td| ||}n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)	r?   r0   LOGdebuggetZ
get_optionZpreferred_ntp_clientsr   which)rA   r;   Z
distro_cfgZdistro_ntp_clientZ	clientcfgZclientr<   r=   r=   r>   select_ntp_client>  s@    

 

 
rF   c                 C   s(   t |rdS |dk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.
    Nr+   )r   rE   )Zinstall_funcr&   r$   r=   r=   r>   install_ntp_clientp  s
    	
rG   c                 C   s    t j| rt| | d  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%   r=   r=   r>   rename_ntp_conf  s    rM   c                 C   sj   g }| }| dkrd}n| dks&| dkr*d}t dtD ]0}|ddd	 t|g|g d
g D  q4|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 r=   r=   ).0nr=   r=   r>   
<listcomp>  s      z)generate_server_names.<locals>.<listcomp>zpool.ntp.org)rangeNR_POOL_SERVERSappendjoinstr)r;   namesZpool_distroxr=   r=   r>   generate_server_names  s    rZ   c           	      C   s  |sg }|sg }t |dkr4t |dkr4| dkr4dS t |dkrl| dkrl|dkrlt| }tdd| n2t |dkrt |dkrt| }tdd| |std	|s|std
||d}|rtjddd}|d }tj	||d t
||| |r
t| 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 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   r*   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poolsztemplate_name-z.tmpl)prefixsuffix   )Zcontent)lenrZ   rB   rC   rV   
ValueErrorr   Zmkstempr	   Z
write_filer   Zrender_to_fileZdel_file)	Zdistro_namer'   r\   r]   rI   template_fnr)   ZparamsZtfiler=   r=   r>   write_ntp_config_template  s@     
 
rd   c                 C   sH  g }t t|  }|r<dt|}|dj|d n"t| 	d| 	dgs^|d t| 
 D ]\}}d| }|dkrt|t|tgs|d	j||d
 qj|dkrt|ts|dj||d
 qj|dkr|dkrqjt|ts&|dj||d
 qjt|tsj|dj||d
 qj|rDt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})keysr)   r(   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}))r)   r(   Nz5Expected a string type for {keypath}. Found ({value})z$Invalid ntp configuration:\n{errors}
)errors)REQUIRED_NTP_CONFIG_KEYS
differencesetre   rV   sortedrU   formatanyrD   itemsall
isinstancerW   listrb   )Z
ntp_configri   Zmissingre   keyrg   rf   r=   r=   r>   supplemental_schema_validation  sl    

 
 
 
 ru   )r0   r<   cloudr   argsreturnc              
   C   sz  d|krt d|  dS |d }|dkr,i }t|tsLtdjt|d|dd}t	
|rrt d|  dS t|d	|j}t	j||d
i gdd}t| t|dd d}|ds|dd|jj}	||	}|sd|d }
t|
t|jj|d|dg |dg |d||dd t|jj|d |d d t	 r(|ddkrz|jdd W n" tjk
r   t d Y nX z|jdd W n" tjk
r   t d Y nX z|jd|d W n4 tjk
r& } zt d|  W 5 d}~X Y nX z|jd |d W n4 tjk
rt } zt d!|  W 5 d}~X Y nX dS )"zEnable and configure ntp.r+   z8Skipping module named %s, not present or disabled by cfgNzL'ntp' key existed in config, but not a dictionary type, is a {_type} instead)Z_typeenabledTz)Skipping module named %s, disabled by cfgrA   Zconfigr5   r%   rL   r)   r(   z{distro}z#No template found, not rendering %sr'   r\   r]   )r'   r\   r]   rI   rc   r)   r&   r$   )r&   r$   r*   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)rB   rC   rr   dictRuntimeErrorrn   r   Zobj_namerD   r	   Zis_falserF   r;   r:   ru   rM   replacer0   Zget_template_filenamerd   rG   Zinstall_packagesZis_BSDZmanage_servicer   ZProcessExecutionErrorZwarningZ	exception)r0   r<   rv   r   rw   Zntp_cfgry   Zntp_client_configrc   r(   msger=   r=   r>   handle'  s     

  

 




  r   )Nr*   )N)NNNNNN)/__doc__r8   rH   Zloggingr   textwrapr   Z	cloudinitr   r   r   r   r   r	   Zcloudinit.cloudr
   Zcloudinit.configr   Zcloudinit.config.schemar   r   Zcloudinit.settingsr   Z	getLogger__name__rB   r3   ZNTP_CONFrT   r2   r9   r7   r;   r4   __annotations__	frozensetrj   r?   rF   rG   rM   rZ   rd   ru   rW   rs   r   r=   r=   r=   r>   <module>   s  
!				/  	  
        
   |	(;
2


      
B>    