U
    Ld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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.d/dd,d0ed0gd0d/dd,d-d1g d-d2dd,d3d4g d5d6dd,d7Zd8d(d9d
g d-d:d;d<d-id<d(id=d*d(d8d>id*d?d8iid
d-d/d@dAd*gd(d+dBdCdDdEgdEdFdGdHd<d(idIdJdKdLdEi id<d(id
d-d9dMd3idNd<d(id
d-d9dMdIidNd<d(id-d
d>dIdJdKdNd<d-id<d(id=d<d(id
d-d9dMdIidNd*d?d8iidOZdPD ]Zed ee< q2dQD ]Zed$ ee< qJdRdSdTedUeedVedWged.gdXZ ee!dY< ee Z e"dMd?dZd<gZ#d[d\ Z$d]d^ Z%dld_d`Z&dmdadbZ'dcdd Z(dndedfZ)dgdh Z*e+eee,ddidjdkZ-dS )oz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   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
        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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_configs<  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>   r/   LOGdebuggetZ
get_optionZpreferred_ntp_clientsr   which)r@   r:   Z
distro_cfgZdistro_ntp_clientZ	clientcfgZclientr;   r<   r<   r=   select_ntp_clientJ  s@    

 

 
rE   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   rD   )Zinstall_funcr%   r#   r<   r<   r=   install_ntp_client|  s
    	
rF   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    rL   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    rY   c	                 C   s$  |sg }|sg }|sg }|s g }t |dkrDt |dkrD| dkrDdS t |dkr|| dkr||dkr|t| }tdd| n2t |dkrt |dkrt| }tdd| |std	|s|std
||||d}	|rt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 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   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poolsallowpeersztemplate_name-z.tmpl)prefixsuffix   )Zcontent)lenrY   rA   rB   rU   
ValueErrorr   Zmkstempr   Z
write_filer   Zrender_to_fileZdel_file)Zdistro_namer&   r[   r\   r]   r^   rH   template_fnr(   ZparamsZtfiler<   r<   r=   write_ntp_config_template  sP      
 re   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setrf   rU   sortedrT   formatanyrC   itemsall
isinstancerV   listrc   )Z
ntp_configrj   Zmissingrf   keyrh   rg   r<   r<   r=   supplemental_schema_validation  sl    

 
 
 
 rv   )r/   r;   cloudargsreturnc                 C   s  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 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	 r|dd krPz|jd!d  W n" tjk
r   t d" Y nX z|jd#d  W n" tjk
rN   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
r }
 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 cfgr@   Zconfigr4   r$   rK   r(   r'   z{distro}z#No template found, not rendering %szservice_name: %sr&   zservers: %sr[   z	pools: %sr\   z	allow: %sr]   z	peers: %sr^   )r&   r[   r\   r]   r^   rH   rd   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)rA   rB   rs   dictRuntimeErrorro   r   Zobj_namerC   r   Zis_falserE   r:   r9   rv   rL   replacer/   Zget_template_filenamere   rF   Zinstall_packagesZis_BSDZmanage_servicer   ZProcessExecutionErrorZwarningZ	exception)r/   r;   rw   rx   Zntp_cfgrz   Zntp_client_configrd   r'   msger<   r<   r=   handleB  s     

  

 





  r   )Nr)   )N)NNNNNNNN).__doc__r7   rG   textwrapr   Z	cloudinitr   Zloggingr   r   r   r   r   Zcloudinit.cloudr	   Zcloudinit.configr
   Zcloudinit.config.schemar   r   Zcloudinit.settingsr   Z	getLogger__name__rA   r2   ZNTP_CONFrS   r1   r8   r6   r:   r3   __annotations__	frozensetrk   r>   rE   rF   rL   rY   re   rv   rV   rt   r   r<   r<   r<   r=   <module>   s  
!				/  	  
        
   |	5H
2


        
Q=