
"·T`]V  ã            1   @   s  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	 d d l 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 j e ƒ Z e Z d Z d Z d d d d d d d d g Z d d d d d d d g d d d d d d i d  d d! d e d d  g d d  d d" d d i d# d d# d e d d# g d d# d d" d d i d$ d d% d d& d g  d d$ d d' d d i i Z d d d d( d d i d  d d d g  d d! i i d d d d( i i d d  d d! i d d d i i d d d d i d  d d d d! i d$ d d) i i d d d d i d  d d d d! i d$ d d) i i d d d d( i i i Z d* d+ d, d- d. d/ d0 e d1 ƒ d2 e d3 e d4 ƒ e d5 ƒ g d6 e d7 d8 d9 d  d7 d8 d: g d9 d; d7 d< d= d7 d> d? d@ i dA dB d0 e dC ƒ i dD d7 d< d= d7 d> d? d@ i dA dB d0 e dE ƒ i dF d7 d> dG dH d0 e dI ƒ i dJ d7 dK dG dB d0 e dL ƒ i dM d0 e dN ƒ d7 d8 g d9 d d7 d> d0 e dO ƒ i d d7 d> d0 e dP ƒ i d d7 d< d= d7 d> i dA dB d0 e dQ ƒ i d d7 d> d0 e dR ƒ i d d7 d> d0 e dS ƒ i i dT g  dU dV dW dX i i dT g  dW dX i i i	 Z e d d d d g ƒ Z e e ƒ Z  dY dZ „  Z d[ d\ „  Z d d! d] d^ „ Z  d d_ d` „ Z! da db „  Z" d d d d d d dc dd „ Z# dX de df „ Z$ dg dh „  Z% di dj „  Z& d S)kzNTP: enable and configure ntpé    N)Údedent)Úlog)Ú
temp_utils)Ú	templater)Ú
type_utils)Úsubp)Úutil)Úget_schema_docÚvalidate_cloudconfig_schema)ÚPER_INSTANCEz/etc/ntp.confé   ÚalpineZcentosZdebianZfedoraÚopensuseZrhelÚslesZubuntuZchronyÚ	check_exeZchronydÚconfpathz/etc/chrony.confÚpackagesÚservice_nameÚtemplate_namezchrony.conf.{distro}ÚtemplateÚntpÚntpdzntp.conf.{distro}Zntpdatezsystemd-timesyncdz/lib/systemd/systemd-timesyncdz-/etc/systemd/timesyncd.conf.d/cloud-init.confztimesyncd.confz/etc/chrony/chrony.confz"/usr/lib/systemd/systemd-timesyncdÚidZcc_ntpÚnameZNTPÚtitlezenable and configure ntpZdescriptionaD          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``.ÚdistrosZexampleszµ        # 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Ú	frequencyÚtypeÚobjectZ
propertiesZnullÚpoolsZarrayÚitemsÚstringÚformatZhostnameZuniqueItemsTa¨                          List of ntp pools. If both pools and servers are
                        empty, 4 default pool servers will be provided of
                        the format ``{0-3}.{distro}.pool.ntp.org``. NOTE:
                        for Alpine Linux when using the Busybox NTP client
                        this setting will be ignored due to the limited
                        functionality of Busybox's ntpd.ÚserverszÚ                        List of ntp servers. If both pools and servers are
                        empty, 4 default pool servers will be provided with
                        the format ``{0-3}.{distro}.pool.ntp.org``.Ú
ntp_clientÚdefaultÚautoa¤                          Name of an NTP client to use to configure system NTP.
                        When unprovided or 'auto' the default client preferred
                        by the distribution will be used. The following
                        built-in client names can be used to override existing
                        configuration defaults: chrony, ntp, ntpdate,
                        systemd-timesyncd.ÚenabledZbooleanz¶                        Attempt to enable ntp clients if set to True.  If set
                        to False, ntp client will not be configured or
                        installedÚconfigzu                        Configuration settings or overrides for the
                        ``ntp_client`` specified.z~                                The path to where the ``ntp_client``
                                configuration is written.zÝ                                The executable name for the ``ntp_client``.
                                For example, ntp service ``check_exe`` is
                                'ntpd' because it runs the ntpd binary.zˆ                                List of packages needed to be installed for the
                                selected ``ntp_client``.z·                                The systemd or sysvinit service name used to
                                start and stop the ``ntp_client``
                                service.aM                                  Inline template allowing users to define their
                                own ``ntp_client`` configuration template.
                                The value must start with '## template:jinja'
                                to enable use of templating support.
                                ZrequiredZminPropertiesé   ZadditionalPropertiesFc             C   sD   t  } t j t ƒ } |  | k r@ t j | | |  g d d ƒ} | S)zòConstruct 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.
    ÚreverseT)ÚDISTRO_CLIENT_CONFIGÚcopyÚNTP_CLIENT_CONFIGr   Úmergemanydict)ÚdistroZdcfgÚcfg© r1   ú9/usr/lib/python3/dist-packages/cloudinit/config/cc_ntp.pyÚdistro_ntp_client_configs'  s
    r3   c             C   s  t  | j ƒ } |  rA |  d k rA t j d |  ƒ | j |  i  ƒ S| j d d ƒ } i  } | d k rì xO | j D]D } | j | ƒ } t j | j d ƒ ƒ ro t j d | ƒ | } Pqo W| s| j d } t j d | ƒ | j | ƒ } n" t j d | ƒ | j | 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.
    r&   z4Selected NTP client "%s" via user-data configurationr$   r   z+Selected NTP client "%s", already installedr   z<Selected distro preferred NTP client "%s", not yet installedz1Selected NTP client "%s" via distro system config)	r3   r   ÚLOGÚdebugÚgetZ
get_optionZpreferred_ntp_clientsr   Úwhich)r$   r/   Z
distro_cfgZdistro_ntp_clientZ	clientcfgZclientr0   r1   r1   r2   Úselect_ntp_client5  s2    
			r8   c             C   s6   t  j | ƒ 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   r7   )Zinstall_funcr   r   r1   r1   r2   Úinstall_ntp_clientb  s
    		r9   c             C   s*   t  j j |  ƒ r& t j |  |  d ƒ d S)zŽRename 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   r1   r1   r2   Úrename_ntp_confs  s    r>   c             C   s‹   g  } |  } |  d k r! d } n |  d k r3 d } xQ t  d t ƒ D]@ } | j d j d d „  t | ƒ g | g d	 g Dƒ ƒ ƒ qC W| S)
zÛGenerate 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   Ú.c             S   s   g  |  ] } | r | ‘ q Sr1   r1   )Ú.0Únr1   r1   r2   ú
<listcomp>’  s   	 z)generate_server_names.<locals>.<listcomp>zpool.ntp.org)ÚrangeÚNR_POOL_SERVERSÚappendÚjoinÚstr)r/   ÚnamesZpool_distroÚxr1   r1   r2   Úgenerate_server_names}  s    	2rK   c       	      C   sV  | s g  } | s g  } t  | ƒ d k rj |  d k rj | d k rj t |  ƒ } t j d d j | ƒ ƒ nI t  | ƒ d k r³ t  | ƒ d k r³ t |  ƒ } t j d d j | ƒ ƒ | sÅ t d ƒ ‚ | rß | rß t d ƒ ‚ d	 | d
 | i } | r,t j d d d d ƒ } | d } t j	 | d | ƒt
 j | | | ƒ | rRt j | ƒ 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   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 providedr#   r   Úprefixztemplate_name-Úsuffixz.tmplr)   ZcontentN)ÚlenrK   r4   r5   rG   Ú
ValueErrorr   Zmkstempr   Z
write_filer   Zrender_to_fileZdel_file)	Zdistro_namer   r#   r   r;   Útemplate_fnr   ZparamsZtfiler1   r1   r2   Úwrite_ntp_config_template—  s2    $
rR   c             C   s>   | r d d |  g } n d |  d g } t  j  | d d ƒd S)a%  Restart or reload an ntp system service.

    @param service: A string specifying the name of the service to be affected.
    @param systemd: A boolean indicating if the distro uses systemd, defaults
    to False.
    @returns: A tuple of stdout, stderr results from executing the action.
    Z	systemctlzreload-or-restartÚserviceZrestartZcaptureTN)r   )rS   ÚsystemdÚcmdr1   r1   r2   Ú
reload_ntpÎ  s    rV   c             C   sá  g  } t  j t |  j ƒ  ƒ ƒ } | rX d j t | ƒ ƒ } | j d j d | ƒ ƒ n1 t |  j	 d ƒ |  j	 d ƒ g ƒ s‰ | j d ƒ x*t |  j
 ƒ  ƒ D]\ } } d | } | d k rû t | t | t ƒ g ƒ s²| j d	 j d
 | d | ƒ ƒ qœ | d k r8t | t ƒ s²| j d j d
 | d | ƒ ƒ qœ | d k r„| d k rSqœ t | t ƒ s²| j d j d
 | d | ƒ ƒ qœ t | t ƒ sœ | j d j d
 | d | ƒ ƒ qœ W| rÝt d j d d j | ƒ ƒ ƒ ‚ 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})Nz5Expected a string type for {keypath}. Found ({value})z$Invalid ntp configuration:\n{errors}ÚerrorsÚ
)ztemplateztemplate_name)ÚREQUIRED_NTP_CONFIG_KEYSÚ
differenceÚsetrW   rG   ÚsortedrF   r"   Úanyr6   r    ÚallÚ
isinstancerH   ÚlistrP   )Z
ntp_configrZ   ZmissingrW   ÚkeyrY   rX   r1   r1   r2   Úsupplemental_schema_validationÝ  sH    

				re   c             C   sh  d | k r  t  j d |  ƒ d S| d } | d k r< i  } t | t ƒ sl t d j d t j | ƒ ƒ ƒ ‚ t | t	 ƒ | j
 d d ƒ } t j | ƒ r® t  j d |  ƒ d St | j
 d	 ƒ | j ƒ } t j | | j
 d
 i  ƒ g d d ƒ} t | ƒ t d | j
 d ƒ ƒ d } | j
 d ƒ sz| j
 d ƒ j d | j j ƒ }	 | j |	 ƒ } | szd | j
 d ƒ }
 t |
 ƒ ‚ t | j j d | j
 d ƒ d | j
 d g  ƒ d | j
 d g  ƒ d | j
 d ƒ d | d | j
 d ƒ ƒt | j j d | d d | d ƒy! t | d d | j j ƒ  ƒWn; t j k
 rc} z t  j d | ƒ ‚  WYd d } ~ Xn Xd 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} insteadZ_typer'   Tz)Skipping module named %s, disabled by cfgr$   r(   r*   r   r   r   z{distro}z#No template found, not rendering %sr   r#   r   r;   rQ   r   r   rT   z&Failed to reload/start ntp service: %s)r4   r5   rb   ÚdictÚRuntimeErrorr"   r   Zobj_namer
   Úschemar6   r   Zis_falser8   r/   r.   re   r>   Úreplacer   Zget_template_filenamerR   r9   Zinstall_packagesrV   Zuses_systemdr   ZProcessExecutionErrorZ	exception)r   r0   Zcloudr   Z_argsZntp_cfgr'   Zntp_client_configrQ   r   ÚmsgÚer1   r1   r2   Úhandle  s`    

	!
	
rl   )'Ú__doc__r,   r:   Útextwrapr   Z	cloudinitr   Zloggingr   r   r   r   r   Zcloudinit.config.schemar	   r
   Zcloudinit.settingsr   Z	getLoggerÚ__name__r4   r   ZNTP_CONFrE   r   r-   r+   rh   Ú	frozensetr\   r3   r8   r9   r>   rK   rR   rV   re   rl   r1   r1   r1   r2   Ú<module>   sT  																									-
	52