
    VhD                         d dl mZmZmZ eZdZd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Zd	Zg d
ZdZdZ G d de      Z G d de      Zd Zedk(  r e        yy)    )absolute_importdivisionprint_functionaw  
module: haproxy
short_description: Enable, disable, and set weights for HAProxy backend servers using socket commands
author:
  - Ravi Bhure (@ravibhure)
description:
  - Enable, disable, drain and set weights for HAProxy backend servers using socket commands.
notes:
  - Enable, disable and drain commands are restricted and can only be issued on sockets configured for level C(admin). For
    example, you can add the line C(stats socket /var/run/haproxy.sock level admin) to the general section of C(haproxy.cfg).
    See U(http://haproxy.1wt.eu/download/1.5/doc/configuration.txt).
  - Depends on netcat (C(nc)) being available; you need to install the appropriate package for your operating system before
    this module can be used.
extends_documentation_fragment:
  - community.general.attributes
attributes:
  check_mode:
    support: none
  diff_mode:
    support: none
options:
  backend:
    description:
      - Name of the HAProxy backend pool.
      - If this parameter is unset, it will be auto-detected.
    type: str
  drain:
    description:
      - Wait until the server has no active connections or until the timeout determined by O(wait_interval) and O(wait_retries)
        is reached.
      - Continue only after the status changes to C(MAINT).
      - This overrides the shutdown_sessions option.
    type: bool
    default: false
  host:
    description:
      - Name of the backend host to change.
    type: str
    required: true
  shutdown_sessions:
    description:
      - When disabling a server, immediately terminate all the sessions attached to the specified server.
      - This can be used to terminate long-running sessions after a server is put into maintenance mode. Overridden by the
        drain option.
    type: bool
    default: false
  socket:
    description:
      - Path to the HAProxy socket file.
    type: path
    default: /var/run/haproxy.sock
  state:
    description:
      - Desired state of the provided backend host.
      - Note that V(drain) state is supported only by HAProxy version 1.5 or later. When used on versions < 1.5, it will be
        ignored.
    type: str
    required: true
    choices: [disabled, drain, enabled]
  agent:
    description:
      - Disable/enable agent checks (depending on O(state) value).
    type: bool
    default: false
    version_added: 1.0.0
  health:
    description:
      - Disable/enable health checks (depending on O(state) value).
    type: bool
    default: false
    version_added: "1.0.0"
  fail_on_not_found:
    description:
      - Fail whenever trying to enable/disable a backend host that does not exist.
    type: bool
    default: false
  wait:
    description:
      - Wait until the server reports a status of C(UP) when O(state=enabled), status of C(MAINT) when O(state=disabled) or
        status of C(DRAIN) when O(state=drain).
    type: bool
    default: false
  wait_interval:
    description:
      - Number of seconds to wait between retries.
    type: int
    default: 5
  wait_retries:
    description:
      - Number of times to check for status after changing the state.
    type: int
    default: 25
  weight:
    description:
      - The value passed in argument.
      - If the value ends with the V(%) sign, then the new weight will be relative to the initially configured weight.
      - Relative weights are only permitted between 0 and 100% and absolute weights are permitted between 0 and 256.
    type: str
aM  
- name: Disable server in 'www' backend pool
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    backend: www

- name: Disable server in 'www' backend pool, also stop health/agent checks
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    health: true
    agent: true

- name: Disable server without backend pool name (apply to all available backend pool)
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'

- name: Disable server, provide socket file
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    socket: /var/run/haproxy.sock
    backend: www

- name: Disable server, provide socket file, wait until status reports in maintenance
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    socket: /var/run/haproxy.sock
    backend: www
    wait: true

# Place server in drain mode, providing a socket file.  Then check the server's
# status every minute to see if it changes to maintenance mode, continuing if it
# does in an hour and failing otherwise.
- community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    socket: /var/run/haproxy.sock
    backend: www
    wait: true
    drain: true
    wait_interval: 60
    wait_retries: 60

- name: Disable backend server in 'www' backend pool and drop open sessions to it
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    backend: www
    socket: /var/run/haproxy.sock
    shutdown_sessions: true

- name: Disable server without backend pool name (apply to all available backend pool) but fail when the backend host is
    not found
  community.general.haproxy:
    state: disabled
    host: '{{ inventory_hostname }}'
    fail_on_not_found: true

- name: Enable server in 'www' backend pool
  community.general.haproxy:
    state: enabled
    host: '{{ inventory_hostname }}'
    backend: www

- name: Enable server in 'www' backend pool wait until healthy
  community.general.haproxy:
    state: enabled
    host: '{{ inventory_hostname }}'
    backend: www
    wait: true

- name: Enable server in 'www' backend pool wait until healthy. Retry 10 times with intervals of 5 seconds to retrieve the
    health
  community.general.haproxy:
    state: enabled
    host: '{{ inventory_hostname }}'
    backend: www
    wait: true
    wait_retries: 10
    wait_interval: 5

- name: Enable server in 'www' backend pool with change server(s) weight
  community.general.haproxy:
    state: enabled
    host: '{{ inventory_hostname }}'
    socket: /var/run/haproxy.sock
    weight: 10
    backend: www

- name: Set the server in 'www' backend pool to drain mode
  community.general.haproxy:
    state: drain
    host: '{{ inventory_hostname }}'
    socket: /var/run/haproxy.sock
    backend: www
N)Template)AnsibleModule)to_bytesto_textz/var/run/haproxy.socki   )enableddisableddrain      c                       e Zd Zy)TimeoutExceptionN)__name__
__module____qualname__     m/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/haproxy.pyr   r      s    r   r   c                   ^    e Zd ZdZd ZddZd Zd Zd ZddZ	d	 Z
d
 Zd Zd ZddZd Zy)HAProxya]  
    Used for communicating with HAProxy through its local UNIX socket interface.
    Perform common tasks in Haproxy related to enable server and
    disable server.

    The complete set of external commands Haproxy handles is documented
    on their website:

    http://haproxy.1wt.eu/download/1.5/doc/configuration.txt#Unix Socket commands
    c                 ,   || _         | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _	        | j                   j                  d	   | _
        | j                   j                  d
   | _        | j                   j                  d   | _        | j                   j                  d   | _        | j                   j                  d   | _        i | _        y )Nstatehostbackendweightsocketshutdown_sessionsfail_on_not_foundagenthealthwaitwait_retrieswait_intervalr   )moduleparamsr   r   r   r   r   r   r    r!   r"   r#   r$   r%   _draincommand_results)selfr&   s     r   __init__zHAProxy.__init__   s5   [[''0
KK&&v.	{{)))4kk((2kk((2!%!3!34G!H!%!3!34G!H[[''0
kk((2KK&&v.	 KK..~>![[//@kk((1!r   c                 6   t        j                   t         j                  t         j                        | _        | j                  j	                  | j                          | j                  j                  t        d|z               d}d}| j                  j                  t              }|r'||z  }| j                  j                  t              }|r't        |d      }|r | j                  ||j                                | j                  j                          |S )z
        Executes a HAProxy command by sending a message to a HAProxy's local
        UNIX socket and waiting up to 'timeout' milliseconds for the response.
        z%s
r   surrogate_or_strict)errors)r   AF_UNIXSOCK_STREAMclientconnectsendallr   recv	RECV_SIZEr	   capture_command_outputstripclose)r*   cmdtimeoutcapture_outputresultbufs         r   executezHAProxy.execute  s    
 mmFNNF4F4FGDKK(HVc\23kky)cMF++""9-C  (=>''V\\^<r   c                     d| j                   vrg | j                   d<   | j                   d   j                  |       d| j                   vrg | j                   d<   | j                   d   j                  |       y)z2
        Capture the output for a command
        commandoutputN)r)   append)r*   r9   rA   s      r   r6   zHAProxy.capture_command_output  sr     D000.0D  +Y'..s34///-/D  *X&--f5r   c           	          | j                  ddd      j                  d      }t        j                  |j	                               }t        t        d t        d |                  S )zw
        Discover all entries with svname = 'BACKEND' and return a list of their corresponding
        pxnames
        	show stat   F# c                     | d   S )Npxnamer   ds    r   <lambda>z/HAProxy.discover_all_backends.<locals>.<lambda>/  s
    1X; r   c                     | d   dk(  S )NsvnameBACKENDr   rI   s    r   rK   z/HAProxy.discover_all_backends.<locals>.<lambda>/  s    8PYAY r   r>   lstripcsv
DictReader
splitlinestuplemapfilter)r*   datars      r   discover_all_backendszHAProxy.discover_all_backends(  sR    
 ||Ke4;;DANN4??,-S.7Y[\0]^__r   c                 \   | j                  ddd      }|j                         }|D cg c]	  }d|v s| }}	 |d   j                  d      d   j                         j	                  dd	      }t        |d         t        |d
         f}|S c c}w # t        t        t        f$ r d}Y |S w xY w)zt
        Attempt to extract the haproxy version.
        Return a tuple containing major and minor version.
        z	show inforE   FzVersion:r   :   .      N)	r>   rS   	partitionr7   splitint
ValueError	TypeError
IndexError)r*   rW   linesxlineversion_valuesversions          r   discover_versionzHAProxy.discover_version1  s    
 ||Ke4! 4aJ!O44	!!W..s3A6<<>DDS!LN>!,-s>!3D/EFG  5 Iz2 	G	s   	BBAB B+*B+Nc                 v   || j                         }n|g}|D ]  }| j                  ||      }| j                  r%|#| j                  j	                  d|d|d       |I| j                  t        |      j                  ||             | j                  s|dk(  r|dk(  r| j                  |||        y)	z
        Run some command on the specified backends. If no backends are provided they will
        be discovered automatically (all backends)
        NzThe specified backend '/z' was not found!msg)rH   rM   DRAINDOWN)
rY   get_state_forr    r&   	fail_jsonr>   r   
substituter#   wait_until_status)r*   r9   rH   rM   wait_for_statusbackendsr   r   s           r   execute_for_backendszHAProxy.execute_for_backendsA  s     >113HxH   
	MG&&w7E&&EM%%JQSYZ & \  Xc]55WV5TU99o&@Uf_**7FOL
	Mr   c           	          | j                  ddd      j                  d      }t        j                  |j	                               }t        t        d t        fd|                  }|xs dS )z
        Find the state of specific services. When pxname is not set, get all backends for a specific host.
        Returns a list of dictionaries containing the status and weight for those services.
        rD   rE   FrF   c                      | d   | d   | d   dS )Nstatusr   scur)r{   r   r|   r   rI   s    r   rK   z'HAProxy.get_state_for.<locals>.<lambda>b  s    Qx[AhKQRSYQZ[ r   c                 4    d u xs | d   k(  xr | d   k(  S )NrH   rM   r   )rJ   rH   rM   s    r   rK   z'HAProxy.get_state_for.<locals>.<lambda>c  s3    &D. #,AhK%+5, "G1281F r   NrO   )r*   rH   rM   rW   rX   r   s    ``   r   rr   zHAProxy.get_state_forY  sj    
 ||Ke4;;DANN4??,-[ GHIK
 }r   c                 <   t        d| j                        D ]V  }| j                  ||      }||d   d   v r| j                  r|d   d   dk(  r yt	        j
                  | j                         X | j                  j                  d|||| j                  fz         y	)
a#  
        Wait for a service to reach the specified status. Try RETRIES times
        with INTERVAL seconds of sleep in between. If the service has not reached
        the expected status in that time, the module will fail. If the service was
        not found, the module will fail.
        r_   r   r{   r|   0Tz8server %s/%s not status '%s' after %d retries. Aborting.rn   N)	ranger$   rr   r(   timesleepr%   r&   rs   )r*   rH   rM   r{   ir   s         r   ru   zHAProxy.wait_until_statusi  s     q$++, 	+A&&vv6E q(++{{eAhv&6#&=JJt))*	+ 	"\%vvt7H7HI#J 	Kr   c                     d}| j                   r|dz  }| j                  r|dz  }|r|d|z  z  }| j                  |||d       y)z
        Enabled action, marks server to UP and checks are re-enabled,
        also supports to get current weight for server (default) and
        set the weight for haproxy backend server when provides.
        z9get weight $pxname/$svname; enable server $pxname/$svnamez; enable agent $pxname/$svnamez; enable health $pxname/$svnamez; set weight $pxname/$svname %sUPNr!   r"   rx   )r*   r   r   r   r9   s        r   r
   zHAProxy.enabled}  sU     J::33C;;44C4v==C!!#wd;r   c                     d}| j                   r|dz  }| j                  r|dz  }|dz  }|r|dz  }| j                  |||d       y)z
        Disabled action, marks server to DOWN for maintenance. In this mode, no more checks will be
        performed on the server until it leaves maintenance,
        also it shutdown sessions while disabling backend host server.
        zget weight $pxname/$svnamez; disable agent $pxname/$svnamez ; disable health $pxname/$svnamez ; disable server $pxname/$svnamez*; shutdown sessions server $pxname/$svnameMAINTNr   )r*   r   r   r   r9   s        r   r   zHAProxy.disabled  sZ     +::44C;;55C11??C!!#wg>r   c                     | j                         }|r@d|k  r:d}| j                  |||d       |dk(  r| j                  ||| j                         yyyy)z
        Drain action, sets the server to DRAIN mode.
        In this mode, the server will not accept any new connections
        other than those that are accepted via persistence.
        )r_   r   z&set server $pxname/$svname state drainrp   r   N)rk   rx   r   r   )r*   r   r   r{   haproxy_versionr9   s         r   r   zHAProxy.drain  sa     //1 v8:C%%c7D'B dGT-C-CD !  9?r   c                    | j                  | j                  | j                        | j                  d<   | j                  dk(  r2| j                  | j                  | j                  | j                         n| j                  dk(  r5| j                  r)| j                  | j                  | j                  d       n| j                  dk(  r2| j                  | j                  | j                  | j                         n_| j                  dk(  r'| j                  | j                  | j                         n)| j                  j                  d| j                  z         | j                  | j                  | j                        | j                  d	<   | j                  d   | j                  d	   k7  | j                  d
<    | j                  j                  di | j                   y)zN
        Figure out what you want to do from ansible, and then do it.
        state_beforer
   r   r   )r{   r   zunknown state specified: '%s'rn   state_afterchangedNr   )rr   r   r   r)   r   r
   r   r(   r   r   r   r&   rs   	exit_json)r*   s    r   actzHAProxy.act  s`   
 04/A/A$,,PTPYPY/Z^, ::"LLDLL$++>ZZ:%$++JJtyy$,,wJ?ZZ:%MM$))T\\43I3IJZZ7"JJtyy$,,/KK!!&E

&R!S /3.@.@tyy.Y]+ ,0+?+?+OSWSgSghuSv+vY'5 4 45r   )rE   T)N)rp   )r   r   r   __doc__r+   r>   r6   rY   rk   rx   rr   ru   r
   r   r   r   r   r   r   r   r      sG    	"$,	6` M0 K(<? E6r   r   c                     t        t        t        ddt              t        dd      t        d      t        d      t        dt              t        dd	      t        dd	      t        dd	      t        dd	      t        dd	      t        d
t              t        d
t
              t        dd	                  } t        s| j                  d       t        |       }|j                          y )NstrT)typerequiredchoices)r   r   )r   path)r   defaultboolFrb   )r   r   r   r   r   r   r    r"   r!   r#   r$   r%   r   )argument_speczunable to locate haproxy socketrn   )
r   dictACTION_CHOICESDEFAULT_SOCKET_LOCATIONWAIT_RETRIESWAIT_INTERVALr   rs   r   r   )r&   ansible_haproxys     r   mainr     s     ED.I540e$U#V-DE">">VU3FE26515,?E=AFE2
F$ >?foOr   __main__)
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESrQ   r   r   stringr   ansible.module_utils.basicr   +ansible.module_utils.common.text.convertersr   r	   r   r5   r   r   r   	Exceptionr   objectr   r   r   r   r   r   <module>r      s    A @bHcJ     4 I 2 	1	y 	[6f [6|8 zF r   