mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-26 21:59:38 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			269 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			269 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| # Copyright Ansible Project
 | |
| # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| from __future__ import absolute_import, division, print_function
 | |
| __metaclass__ = type
 | |
| 
 | |
| 
 | |
| DOCUMENTATION = '''
 | |
| ---
 | |
| module: ovh_ip_failover
 | |
| short_description: Manage OVH IP failover address
 | |
| description:
 | |
|     - Manage OVH (French European hosting provider) IP Failover Address. For now, this module can only be used to move
 | |
|       an ip failover (or failover block) between services
 | |
| author: "Pascal HERAUD (@pascalheraud)"
 | |
| notes:
 | |
|     - Uses the python OVH Api U(https://github.com/ovh/python-ovh).
 | |
|       You have to create an application (a key and secret) with a consumer
 | |
|       key as described into U(https://docs.ovh.com/gb/en/customer/first-steps-with-ovh-api/)
 | |
| requirements:
 | |
|     - ovh >=  0.4.8
 | |
| extends_documentation_fragment:
 | |
|     - community.general.attributes
 | |
| attributes:
 | |
|     check_mode:
 | |
|         support: full
 | |
|     diff_mode:
 | |
|         support: none
 | |
| options:
 | |
|     name:
 | |
|         required: true
 | |
|         description:
 | |
|             - The IP address to manage (can be a single IP like 1.1.1.1
 | |
|               or a block like 1.1.1.1/28 )
 | |
|         type: str
 | |
|     service:
 | |
|         required: true
 | |
|         description:
 | |
|             - The name of the OVH service this IP address should be routed
 | |
|         type: str
 | |
|     endpoint:
 | |
|         required: true
 | |
|         description:
 | |
|             - The endpoint to use ( for instance ovh-eu)
 | |
|         type: str
 | |
|     wait_completion:
 | |
|         required: false
 | |
|         default: true
 | |
|         type: bool
 | |
|         description:
 | |
|             - If true, the module will wait for the IP address to be moved.
 | |
|               If false, exit without waiting. The taskId will be returned
 | |
|               in module output
 | |
|     wait_task_completion:
 | |
|         required: false
 | |
|         default: 0
 | |
|         description:
 | |
|             - If not 0, the module will wait for this task id to be
 | |
|               completed. Use wait_task_completion if you want to wait for
 | |
|               completion of a previously executed task with
 | |
|               wait_completion=false. You can execute this module repeatedly on
 | |
|               a list of failover IPs using wait_completion=false (see examples)
 | |
|         type: int
 | |
|     application_key:
 | |
|         required: true
 | |
|         description:
 | |
|             - The applicationKey to use
 | |
|         type: str
 | |
|     application_secret:
 | |
|         required: true
 | |
|         description:
 | |
|             - The application secret to use
 | |
|         type: str
 | |
|     consumer_key:
 | |
|         required: true
 | |
|         description:
 | |
|             - The consumer key to use
 | |
|         type: str
 | |
|     timeout:
 | |
|         required: false
 | |
|         default: 120
 | |
|         description:
 | |
|             - The timeout in seconds used to wait for a task to be
 | |
|               completed. Default is 120 seconds.
 | |
|         type: int
 | |
| 
 | |
| '''
 | |
| 
 | |
| EXAMPLES = '''
 | |
| # Route an IP address 1.1.1.1 to the service ns666.ovh.net
 | |
| - community.general.ovh_ip_failover:
 | |
|     name: 1.1.1.1
 | |
|     service: ns666.ovh.net
 | |
|     endpoint: ovh-eu
 | |
|     application_key: yourkey
 | |
|     application_secret: yoursecret
 | |
|     consumer_key: yourconsumerkey
 | |
| - community.general.ovh_ip_failover:
 | |
|     name: 1.1.1.1
 | |
|     service: ns666.ovh.net
 | |
|     endpoint: ovh-eu
 | |
|     wait_completion: false
 | |
|     application_key: yourkey
 | |
|     application_secret: yoursecret
 | |
|     consumer_key: yourconsumerkey
 | |
|   register: moved
 | |
| - community.general.ovh_ip_failover:
 | |
|     name: 1.1.1.1
 | |
|     service: ns666.ovh.net
 | |
|     endpoint: ovh-eu
 | |
|     wait_task_completion: "{{moved.taskId}}"
 | |
|     application_key: yourkey
 | |
|     application_secret: yoursecret
 | |
|     consumer_key: yourconsumerkey
 | |
| '''
 | |
| 
 | |
| RETURN = '''
 | |
| '''
 | |
| 
 | |
| import time
 | |
| 
 | |
| try:
 | |
|     import ovh
 | |
|     import ovh.exceptions
 | |
|     from ovh.exceptions import APIError
 | |
|     HAS_OVH = True
 | |
| except ImportError:
 | |
|     HAS_OVH = False
 | |
| 
 | |
| from ansible.module_utils.basic import AnsibleModule
 | |
| from ansible.module_utils.six.moves.urllib.parse import quote_plus
 | |
| 
 | |
| 
 | |
| def getOvhClient(ansibleModule):
 | |
|     endpoint = ansibleModule.params.get('endpoint')
 | |
|     application_key = ansibleModule.params.get('application_key')
 | |
|     application_secret = ansibleModule.params.get('application_secret')
 | |
|     consumer_key = ansibleModule.params.get('consumer_key')
 | |
| 
 | |
|     return ovh.Client(
 | |
|         endpoint=endpoint,
 | |
|         application_key=application_key,
 | |
|         application_secret=application_secret,
 | |
|         consumer_key=consumer_key
 | |
|     )
 | |
| 
 | |
| 
 | |
| def waitForNoTask(client, name, timeout):
 | |
|     currentTimeout = timeout
 | |
|     while client.get('/ip/{0}/task'.format(quote_plus(name)),
 | |
|                      function='genericMoveFloatingIp',
 | |
|                      status='todo'):
 | |
|         time.sleep(1)  # Delay for 1 sec
 | |
|         currentTimeout -= 1
 | |
|         if currentTimeout < 0:
 | |
|             return False
 | |
|     return True
 | |
| 
 | |
| 
 | |
| def waitForTaskDone(client, name, taskId, timeout):
 | |
|     currentTimeout = timeout
 | |
|     while True:
 | |
|         task = client.get('/ip/{0}/task/{1}'.format(quote_plus(name), taskId))
 | |
|         if task['status'] == 'done':
 | |
|             return True
 | |
|         time.sleep(5)  # Delay for 5 sec because it's long to wait completion, do not harass the API
 | |
|         currentTimeout -= 5
 | |
|         if currentTimeout < 0:
 | |
|             return False
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     module = AnsibleModule(
 | |
|         argument_spec=dict(
 | |
|             name=dict(required=True),
 | |
|             service=dict(required=True),
 | |
|             endpoint=dict(required=True),
 | |
|             wait_completion=dict(default=True, type='bool'),
 | |
|             wait_task_completion=dict(default=0, type='int'),
 | |
|             application_key=dict(required=True, no_log=True),
 | |
|             application_secret=dict(required=True, no_log=True),
 | |
|             consumer_key=dict(required=True, no_log=True),
 | |
|             timeout=dict(default=120, type='int')
 | |
|         ),
 | |
|         supports_check_mode=True
 | |
|     )
 | |
| 
 | |
|     result = dict(
 | |
|         changed=False
 | |
|     )
 | |
| 
 | |
|     if not HAS_OVH:
 | |
|         module.fail_json(msg='ovh-api python module is required to run this module ')
 | |
| 
 | |
|     # Get parameters
 | |
|     name = module.params.get('name')
 | |
|     service = module.params.get('service')
 | |
|     timeout = module.params.get('timeout')
 | |
|     wait_completion = module.params.get('wait_completion')
 | |
|     wait_task_completion = module.params.get('wait_task_completion')
 | |
| 
 | |
|     # Connect to OVH API
 | |
|     client = getOvhClient(module)
 | |
| 
 | |
|     # Check that the load balancing exists
 | |
|     try:
 | |
|         ips = client.get('/ip', ip=name, type='failover')
 | |
|     except APIError as apiError:
 | |
|         module.fail_json(
 | |
|             msg='Unable to call OVH api for getting the list of ips, '
 | |
|                 'check application key, secret, consumerkey and parameters. '
 | |
|                 'Error returned by OVH api was : {0}'.format(apiError))
 | |
| 
 | |
|     if name not in ips and '{0}/32'.format(name) not in ips:
 | |
|         module.fail_json(msg='IP {0} does not exist'.format(name))
 | |
| 
 | |
|     # Check that no task is pending before going on
 | |
|     try:
 | |
|         if not waitForNoTask(client, name, timeout):
 | |
|             module.fail_json(
 | |
|                 msg='Timeout of {0} seconds while waiting for no pending '
 | |
|                     'tasks before executing the module '.format(timeout))
 | |
|     except APIError as apiError:
 | |
|         module.fail_json(
 | |
|             msg='Unable to call OVH api for getting the list of pending tasks '
 | |
|                 'of the ip, check application key, secret, consumerkey '
 | |
|                 'and parameters. Error returned by OVH api was : {0}'
 | |
|                 .format(apiError))
 | |
| 
 | |
|     try:
 | |
|         ipproperties = client.get('/ip/{0}'.format(quote_plus(name)))
 | |
|     except APIError as apiError:
 | |
|         module.fail_json(
 | |
|             msg='Unable to call OVH api for getting the properties '
 | |
|                 'of the ip, check application key, secret, consumerkey '
 | |
|                 'and parameters. Error returned by OVH api was : {0}'
 | |
|             .format(apiError))
 | |
| 
 | |
|     if ipproperties['routedTo']['serviceName'] != service:
 | |
|         if not module.check_mode:
 | |
|             if wait_task_completion == 0:
 | |
|                 # Move the IP and get the created taskId
 | |
|                 task = client.post('/ip/{0}/move'.format(quote_plus(name)), to=service)
 | |
|                 taskId = task['taskId']
 | |
|                 result['moved'] = True
 | |
|             else:
 | |
|                 # Just wait for the given taskId to be completed
 | |
|                 taskId = wait_task_completion
 | |
|                 result['moved'] = False
 | |
|             result['taskId'] = taskId
 | |
|             if wait_completion or wait_task_completion != 0:
 | |
|                 if not waitForTaskDone(client, name, taskId, timeout):
 | |
|                     module.fail_json(
 | |
|                         msg='Timeout of {0} seconds while waiting for completion '
 | |
|                             'of move ip to service'.format(timeout))
 | |
|                 result['waited'] = True
 | |
|             else:
 | |
|                 result['waited'] = False
 | |
|         result['changed'] = True
 | |
| 
 | |
|     module.exit_json(**result)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |