summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/general/plugins/modules/infinity.py
diff options
context:
space:
mode:
Diffstat (limited to 'ansible_collections/community/general/plugins/modules/infinity.py')
-rw-r--r--ansible_collections/community/general/plugins/modules/infinity.py575
1 files changed, 575 insertions, 0 deletions
diff --git a/ansible_collections/community/general/plugins/modules/infinity.py b/ansible_collections/community/general/plugins/modules/infinity.py
new file mode 100644
index 000000000..65aa591f4
--- /dev/null
+++ b/ansible_collections/community/general/plugins/modules/infinity.py
@@ -0,0 +1,575 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017, <meiliu@fusionlayer.com>
+# 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 = r'''
+module: infinity
+short_description: Manage Infinity IPAM using Rest API
+description:
+ - Manage Infinity IPAM using REST API.
+author:
+ - Meirong Liu (@MeganLiu)
+extends_documentation_fragment:
+ - community.general.attributes
+attributes:
+ check_mode:
+ support: none
+ diff_mode:
+ support: none
+options:
+ server_ip:
+ description:
+ - Infinity server_ip with IP address.
+ type: str
+ required: true
+ username:
+ description:
+ - Username to access Infinity.
+ - The user must have REST API privileges.
+ type: str
+ required: true
+ password:
+ description:
+ - Infinity password.
+ type: str
+ required: true
+ action:
+ description:
+ - Action to perform
+ type: str
+ required: true
+ choices: [add_network, delete_network, get_network, get_network_id, release_ip, release_network, reserve_network, reserve_next_available_ip ]
+ network_id:
+ description:
+ - Network ID.
+ type: str
+ ip_address:
+ description:
+ - IP Address for a reservation or a release.
+ type: str
+ network_address:
+ description:
+ - Network address with CIDR format (e.g., 192.168.310.0).
+ type: str
+ network_size:
+ description:
+ - Network bitmask (e.g. 255.255.255.220) or CIDR format (e.g., /26).
+ type: str
+ network_name:
+ description:
+ - The name of a network.
+ type: str
+ network_location:
+ description:
+ - The parent network id for a given network.
+ type: int
+ default: -1
+ network_type:
+ description:
+ - Network type defined by Infinity
+ type: str
+ choices: [ lan, shared_lan, supernet ]
+ default: lan
+ network_family:
+ description:
+ - Network family defined by Infinity, e.g. IPv4, IPv6 and Dual stack
+ type: str
+ choices: [ '4', '6', dual ]
+ default: '4'
+'''
+
+EXAMPLES = r'''
+---
+- hosts: localhost
+ connection: local
+ strategy: debug
+ tasks:
+ - name: Reserve network into Infinity IPAM
+ community.general.infinity:
+ server_ip: 80.75.107.12
+ username: username
+ password: password
+ action: reserve_network
+ network_name: reserve_new_ansible_network
+ network_family: 4
+ network_type: lan
+ network_id: 1201
+ network_size: /28
+ register: infinity
+'''
+
+RETURN = r'''
+network_id:
+ description: id for a given network
+ returned: success
+ type: str
+ sample: '1501'
+ip_info:
+ description: when reserve next available ip address from a network, the ip address info ) is returned.
+ returned: success
+ type: str
+ sample: '{"address": "192.168.10.3", "hostname": "", "FQDN": "", "domainname": "", "id": 3229}'
+network_info:
+ description: when reserving a LAN network from a Infinity supernet by providing network_size, the information about the reserved network is returned.
+ returned: success
+ type: str
+ sample: {
+ "network_address": "192.168.10.32/28",
+ "network_family": "4",
+ "network_id": 3102,
+ "network_size": null,
+ "description": null,
+ "network_location": "3085",
+ "ranges": { "id": 0, "name": null,"first_ip": null,"type": null,"last_ip": null},
+ "network_type": "lan",
+ "network_name": "'reserve_new_ansible_network'"
+ }
+'''
+
+
+from ansible.module_utils.basic import AnsibleModule, json
+from ansible.module_utils.urls import open_url
+
+
+class Infinity(object):
+ """
+ Class for manage REST API calls with the Infinity.
+ """
+
+ def __init__(self, module, server_ip, username, password):
+ self.module = module
+ self.auth_user = username
+ self.auth_pass = password
+ self.base_url = "https://%s/rest/v1/" % (str(server_ip))
+
+ def _get_api_call_ansible_handler(
+ self,
+ method='get',
+ resource_url='',
+ stat_codes=None,
+ params=None,
+ payload_data=None):
+ """
+ Perform the HTTPS request by using ansible get/delete method
+ """
+ stat_codes = [200] if stat_codes is None else stat_codes
+ request_url = str(self.base_url) + str(resource_url)
+ response = None
+ headers = {'Content-Type': 'application/json'}
+ if not request_url:
+ self.module.exit_json(
+ msg="When sending Rest api call , the resource URL is empty, please check.")
+ if payload_data and not isinstance(payload_data, str):
+ payload_data = json.dumps(payload_data)
+ response_raw = open_url(
+ str(request_url),
+ method=method,
+ timeout=20,
+ headers=headers,
+ url_username=self.auth_user,
+ url_password=self.auth_pass,
+ validate_certs=False,
+ force_basic_auth=True,
+ data=payload_data)
+
+ response = response_raw.read()
+ payload = ''
+ if response_raw.code not in stat_codes:
+ self.module.exit_json(
+ changed=False,
+ meta=" openurl response_raw.code show error and error code is %r" %
+ (response_raw.code))
+ else:
+ if isinstance(response, str) and len(response) > 0:
+ payload = response
+ elif method.lower() == 'delete' and response_raw.code == 204:
+ payload = 'Delete is done.'
+ if isinstance(payload, dict) and "text" in payload:
+ self.module.exit_json(
+ changed=False,
+ meta="when calling rest api, returned data is not json ")
+ raise Exception(payload["text"])
+ return payload
+
+ # ---------------------------------------------------------------------------
+ # get_network()
+ # ---------------------------------------------------------------------------
+ def get_network(self, network_id, network_name, limit=-1):
+ """
+ Search network_name inside Infinity by using rest api
+ Network id or network_name needs to be provided
+ return the details of a given with given network_id or name
+ """
+ if network_name is None and network_id is None:
+ self.module.exit_json(
+ msg="You must specify one of the options 'network_name' or 'network_id'.")
+ method = "get"
+ resource_url = ''
+ params = {}
+ response = None
+ if network_id:
+ resource_url = "networks/" + str(network_id)
+ response = self._get_api_call_ansible_handler(method, resource_url)
+ if network_id is None and network_name:
+ method = "get"
+ resource_url = "search"
+ params = {"query": json.dumps(
+ {"name": network_name, "type": "network"})}
+ response = self._get_api_call_ansible_handler(
+ method, resource_url, payload_data=json.dumps(params))
+ if response and isinstance(response, str):
+ response = json.loads(response)
+ if response and isinstance(response, list) and len(
+ response) > 1 and limit == 1:
+ response = response[0]
+ response = json.dumps(response)
+ return response
+
+ # ---------------------------------------------------------------------------
+ # get_network_id()
+ # ---------------------------------------------------------------------------
+ def get_network_id(self, network_name="", network_type='lan'):
+ """
+ query network_id from Infinity via rest api based on given network_name
+ """
+ method = 'get'
+ resource_url = 'search'
+ response = None
+ if network_name is None:
+ self.module.exit_json(
+ msg="You must specify the option 'network_name'")
+ params = {"query": json.dumps(
+ {"name": network_name, "type": "network"})}
+ response = self._get_api_call_ansible_handler(
+ method, resource_url, payload_data=json.dumps(params))
+ network_id = ""
+ if response and isinstance(response, str):
+ response = json.loads(response)
+ if response and isinstance(response, list):
+ response = response[0]
+ network_id = response['id']
+ return network_id
+
+ # ---------------------------------------------------------------------------
+ # reserve_next_available_ip()
+ # ---------------------------------------------------------------------------
+ def reserve_next_available_ip(self, network_id=""):
+ """
+ Reserve ip address via Infinity by using rest api
+ network_id: the id of the network that users would like to reserve network from
+ return the next available ip address from that given network
+ """
+ method = "post"
+ resource_url = ''
+ response = None
+ ip_info = ''
+ if not network_id:
+ self.module.exit_json(
+ msg="You must specify the option 'network_id'.")
+ if network_id:
+ resource_url = "networks/" + str(network_id) + "/reserve_ip"
+ response = self._get_api_call_ansible_handler(method, resource_url)
+ if response and response.find(
+ "[") >= 0 and response.find("]") >= 0:
+ start_pos = response.find("{")
+ end_pos = response.find("}")
+ ip_info = response[start_pos: (end_pos + 1)]
+ return ip_info
+
+ # -------------------------
+ # release_ip()
+ # -------------------------
+ def release_ip(self, network_id="", ip_address=""):
+ """
+ Reserve ip address via Infinity by using rest api
+ """
+ method = "get"
+ resource_url = ''
+ response = None
+ if ip_address is None or network_id is None:
+ self.module.exit_json(
+ msg="You must specify those two options: 'network_id' and 'ip_address'.")
+
+ resource_url = "networks/" + str(network_id) + "/children"
+ response = self._get_api_call_ansible_handler(method, resource_url)
+ if not response:
+ self.module.exit_json(
+ msg="There is an error in release ip %s from network %s." %
+ (ip_address, network_id))
+
+ ip_list = json.loads(response)
+ ip_idlist = []
+ for ip_item in ip_list:
+ ip_id = ip_item['id']
+ ip_idlist.append(ip_id)
+ deleted_ip_id = ''
+ for ip_id in ip_idlist:
+ ip_response = ''
+ resource_url = "ip_addresses/" + str(ip_id)
+ ip_response = self._get_api_call_ansible_handler(
+ method,
+ resource_url,
+ stat_codes=[200])
+ if ip_response and json.loads(
+ ip_response)['address'] == str(ip_address):
+ deleted_ip_id = ip_id
+ break
+ if deleted_ip_id:
+ method = 'delete'
+ resource_url = "ip_addresses/" + str(deleted_ip_id)
+ response = self._get_api_call_ansible_handler(
+ method, resource_url, stat_codes=[204])
+ else:
+ self.module.exit_json(
+ msg=" When release ip, could not find the ip address %r from the given network %r' ." %
+ (ip_address, network_id))
+
+ return response
+
+ # -------------------
+ # delete_network()
+ # -------------------
+ def delete_network(self, network_id="", network_name=""):
+ """
+ delete network from Infinity by using rest api
+ """
+ method = 'delete'
+ resource_url = ''
+ response = None
+ if network_id is None and network_name is None:
+ self.module.exit_json(
+ msg="You must specify one of those options: 'network_id','network_name' .")
+ if network_id is None and network_name:
+ network_id = self.get_network_id(network_name=network_name)
+ if network_id:
+ resource_url = "networks/" + str(network_id)
+ response = self._get_api_call_ansible_handler(
+ method, resource_url, stat_codes=[204])
+ return response
+
+ # reserve_network()
+ # ---------------------------------------------------------------------------
+ def reserve_network(self, network_id="",
+ reserved_network_name="", reserved_network_description="",
+ reserved_network_size="", reserved_network_family='4',
+ reserved_network_type='lan', reserved_network_address="",):
+ """
+ Reserves the first available network of specified size from a given supernet
+ <dt>network_name (required)</dt><dd>Name of the network</dd>
+ <dt>description (optional)</dt><dd>Free description</dd>
+ <dt>network_family (required)</dt><dd>Address family of the network. One of '4', '6', 'IPv4', 'IPv6', 'dual'</dd>
+ <dt>network_address (optional)</dt><dd>Address of the new network. If not given, the first network available will be created.</dd>
+ <dt>network_size (required)</dt><dd>Size of the new network in /&lt;prefix&gt; notation.</dd>
+ <dt>network_type (required)</dt><dd>Type of network. One of 'supernet', 'lan', 'shared_lan'</dd>
+
+ """
+ method = 'post'
+ resource_url = ''
+ network_info = None
+ if network_id is None or reserved_network_name is None or reserved_network_size is None:
+ self.module.exit_json(
+ msg="You must specify those options: 'network_id', 'reserved_network_name' and 'reserved_network_size'")
+ if network_id:
+ resource_url = "networks/" + str(network_id) + "/reserve_network"
+ if not reserved_network_family:
+ reserved_network_family = '4'
+ if not reserved_network_type:
+ reserved_network_type = 'lan'
+ payload_data = {
+ "network_name": reserved_network_name,
+ 'description': reserved_network_description,
+ 'network_size': reserved_network_size,
+ 'network_family': reserved_network_family,
+ 'network_type': reserved_network_type,
+ 'network_location': int(network_id)}
+ if reserved_network_address:
+ payload_data.update({'network_address': reserved_network_address})
+
+ network_info = self._get_api_call_ansible_handler(
+ method, resource_url, stat_codes=[200, 201], payload_data=payload_data)
+
+ return network_info
+
+ # ---------------------------------------------------------------------------
+ # release_network()
+ # ---------------------------------------------------------------------------
+ def release_network(
+ self,
+ network_id="",
+ released_network_name="",
+ released_network_type='lan'):
+ """
+ Release the network with name 'released_network_name' from the given supernet network_id
+ """
+ method = 'get'
+ response = None
+ if network_id is None or released_network_name is None:
+ self.module.exit_json(
+ msg="You must specify those options 'network_id', 'reserved_network_name' and 'reserved_network_size'")
+ matched_network_id = ""
+ resource_url = "networks/" + str(network_id) + "/children"
+ response = self._get_api_call_ansible_handler(method, resource_url)
+ if not response:
+ self.module.exit_json(
+ msg=" there is an error in releasing network %r from network %s." %
+ (network_id, released_network_name))
+ if response:
+ response = json.loads(response)
+ for child_net in response:
+ if child_net['network'] and child_net['network']['network_name'] == released_network_name:
+ matched_network_id = child_net['network']['network_id']
+ break
+ response = None
+ if matched_network_id:
+ method = 'delete'
+ resource_url = "networks/" + str(matched_network_id)
+ response = self._get_api_call_ansible_handler(
+ method, resource_url, stat_codes=[204])
+ else:
+ self.module.exit_json(
+ msg=" When release network , could not find the network %r from the given superent %r' " %
+ (released_network_name, network_id))
+
+ return response
+
+ # ---------------------------------------------------------------------------
+ # add_network()
+ # ---------------------------------------------------------------------------
+ def add_network(
+ self, network_name="", network_address="",
+ network_size="", network_family='4',
+ network_type='lan', network_location=-1):
+ """
+ add a new LAN network into a given supernet Fusionlayer Infinity via rest api or default supernet
+ required fields=['network_name', 'network_family', 'network_type', 'network_address','network_size' ]
+ """
+ method = 'post'
+ resource_url = 'networks'
+ response = None
+ if network_name is None or network_address is None or network_size is None:
+ self.module.exit_json(
+ msg="You must specify those options 'network_name', 'network_address' and 'network_size'")
+
+ if not network_family:
+ network_family = '4'
+ if not network_type:
+ network_type = 'lan'
+ if not network_location:
+ network_location = -1
+ payload_data = {
+ "network_name": network_name,
+ 'network_address': network_address,
+ 'network_size': network_size,
+ 'network_family': network_family,
+ 'network_type': network_type,
+ 'network_location': network_location}
+ response = self._get_api_call_ansible_handler(
+ method='post', resource_url=resource_url,
+ stat_codes=[200], payload_data=payload_data)
+ return response
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec=dict(
+ server_ip=dict(type='str', required=True),
+ username=dict(type='str', required=True),
+ password=dict(type='str', required=True, no_log=True),
+ network_id=dict(type='str'),
+ ip_address=dict(type='str'),
+ network_name=dict(type='str'),
+ network_location=dict(type='int', default=-1),
+ network_family=dict(type='str', default='4', choices=['4', '6', 'dual']),
+ network_type=dict(type='str', default='lan', choices=['lan', 'shared_lan', 'supernet']),
+ network_address=dict(type='str'),
+ network_size=dict(type='str'),
+ action=dict(type='str', required=True, choices=[
+ 'add_network',
+ 'delete_network',
+ 'get_network',
+ 'get_network_id',
+ 'release_ip',
+ 'release_network',
+ 'reserve_network',
+ 'reserve_next_available_ip',
+ ],),
+ ),
+ required_together=(
+ ['username', 'password'],
+ ),
+ )
+ server_ip = module.params["server_ip"]
+ username = module.params["username"]
+ password = module.params["password"]
+ action = module.params["action"]
+ network_id = module.params["network_id"]
+ released_ip = module.params["ip_address"]
+ network_name = module.params["network_name"]
+ network_family = module.params["network_family"]
+ network_type = module.params["network_type"]
+ network_address = module.params["network_address"]
+ network_size = module.params["network_size"]
+ network_location = module.params["network_location"]
+ my_infinity = Infinity(module, server_ip, username, password)
+ result = ''
+ if action == "reserve_next_available_ip":
+ if network_id:
+ result = my_infinity.reserve_next_available_ip(network_id)
+ if not result:
+ result = 'There is an error in calling method of reserve_next_available_ip'
+ module.exit_json(changed=False, meta=result)
+ module.exit_json(changed=True, meta=result)
+ elif action == "release_ip":
+ if network_id and released_ip:
+ result = my_infinity.release_ip(
+ network_id=network_id, ip_address=released_ip)
+ module.exit_json(changed=True, meta=result)
+ elif action == "delete_network":
+ result = my_infinity.delete_network(
+ network_id=network_id, network_name=network_name)
+ module.exit_json(changed=True, meta=result)
+
+ elif action == "get_network_id":
+ result = my_infinity.get_network_id(
+ network_name=network_name, network_type=network_type)
+ module.exit_json(changed=True, meta=result)
+ elif action == "get_network":
+ result = my_infinity.get_network(
+ network_id=network_id, network_name=network_name)
+ module.exit_json(changed=True, meta=result)
+ elif action == "reserve_network":
+ result = my_infinity.reserve_network(
+ network_id=network_id,
+ reserved_network_name=network_name,
+ reserved_network_size=network_size,
+ reserved_network_family=network_family,
+ reserved_network_type=network_type,
+ reserved_network_address=network_address)
+ module.exit_json(changed=True, meta=result)
+ elif action == "release_network":
+ result = my_infinity.release_network(
+ network_id=network_id,
+ released_network_name=network_name,
+ released_network_type=network_type)
+ module.exit_json(changed=True, meta=result)
+
+ elif action == "add_network":
+ result = my_infinity.add_network(
+ network_name=network_name,
+ network_location=network_location,
+ network_address=network_address,
+ network_size=network_size,
+ network_family=network_family,
+ network_type=network_type)
+
+ module.exit_json(changed=True, meta=result)
+
+
+if __name__ == '__main__':
+ main()