1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00
community.general/plugins/modules/dimensiondata_network.py
Felix Fontein 673c79f6d9
Add attributes to apache2, cobbler, dimensiondata, icinga2, lxca, pritunl, and spectrum modules (#5963)
Add attributes to apache2, cobbler, dimensiondata, icinga2, lxca, pritunl, and spectrum modules.
2023-02-24 09:24:37 +01:00

303 lines
9 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016 Dimension Data
# Authors:
# - Aimon Bustardo <aimon.bustardo@dimensiondata.com>
# - Bert Diwa <Lamberto.Diwa@dimensiondata.com>
# - Adam Friedman <tintoy@tintoy.io>
#
# 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: dimensiondata_network
short_description: Create, update, and delete MCP 1.0 & 2.0 networks
extends_documentation_fragment:
- community.general.dimensiondata
- community.general.dimensiondata_wait
- community.general.attributes
description:
- Create, update, and delete MCP 1.0 & 2.0 networks
author: 'Aimon Bustardo (@aimonb)'
attributes:
check_mode:
support: none
diff_mode:
support: none
options:
name:
description:
- The name of the network domain to create.
required: true
type: str
description:
description:
- Additional description of the network domain.
required: false
type: str
service_plan:
description:
- The service plan, either "ESSENTIALS" or "ADVANCED".
- MCP 2.0 Only.
choices: [ESSENTIALS, ADVANCED]
default: ESSENTIALS
type: str
state:
description:
- Should the resource be present or absent.
choices: [present, absent]
default: present
type: str
'''
EXAMPLES = '''
- name: Create an MCP 1.0 network
community.general.dimensiondata_network:
region: na
location: NA5
name: mynet
- name: Create an MCP 2.0 network
community.general.dimensiondata_network:
region: na
mcp_user: my_user
mcp_password: my_password
location: NA9
name: mynet
service_plan: ADVANCED
- name: Delete a network
community.general.dimensiondata_network:
region: na
location: NA1
name: mynet
state: absent
'''
RETURN = '''
network:
description: Dictionary describing the network.
returned: On success when I(state=present).
type: complex
contains:
id:
description: Network ID.
type: str
sample: "8c787000-a000-4050-a215-280893411a7d"
name:
description: Network name.
type: str
sample: "My network"
description:
description: Network description.
type: str
sample: "My network description"
location:
description: Datacenter location.
type: str
sample: NA3
status:
description: Network status. (MCP 2.0 only)
type: str
sample: NORMAL
private_net:
description: Private network subnet. (MCP 1.0 only)
type: str
sample: "10.2.3.0"
multicast:
description: Multicast enabled? (MCP 1.0 only)
type: bool
sample: false
'''
import traceback
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.dimensiondata import HAS_LIBCLOUD, DimensionDataModule
from ansible.module_utils.common.text.converters import to_native
if HAS_LIBCLOUD:
from libcloud.compute.base import NodeLocation
from libcloud.common.dimensiondata import DimensionDataAPIException
class DimensionDataNetworkModule(DimensionDataModule):
"""
The dimensiondata_network module for Ansible.
"""
def __init__(self):
"""
Create a new Dimension Data network module.
"""
super(DimensionDataNetworkModule, self).__init__(
module=AnsibleModule(
argument_spec=DimensionDataModule.argument_spec_with_wait(
name=dict(type='str', required=True),
description=dict(type='str', required=False),
service_plan=dict(default='ESSENTIALS', choices=['ADVANCED', 'ESSENTIALS']),
state=dict(default='present', choices=['present', 'absent'])
),
required_together=DimensionDataModule.required_together()
)
)
self.name = self.module.params['name']
self.description = self.module.params['description']
self.service_plan = self.module.params['service_plan']
self.state = self.module.params['state']
def state_present(self):
network = self._get_network()
if network:
self.module.exit_json(
changed=False,
msg='Network already exists',
network=self._network_to_dict(network)
)
network = self._create_network()
self.module.exit_json(
changed=True,
msg='Created network "%s" in datacenter "%s".' % (self.name, self.location),
network=self._network_to_dict(network)
)
def state_absent(self):
network = self._get_network()
if not network:
self.module.exit_json(
changed=False,
msg='Network "%s" does not exist' % self.name,
network=self._network_to_dict(network)
)
self._delete_network(network)
def _get_network(self):
if self.mcp_version == '1.0':
networks = self.driver.list_networks(location=self.location)
else:
networks = self.driver.ex_list_network_domains(location=self.location)
matched_network = [network for network in networks if network.name == self.name]
if matched_network:
return matched_network[0]
return None
def _network_to_dict(self, network):
network_dict = dict(
id=network.id,
name=network.name,
description=network.description
)
if isinstance(network.location, NodeLocation):
network_dict['location'] = network.location.id
else:
network_dict['location'] = network.location
if self.mcp_version == '1.0':
network_dict['private_net'] = network.private_net
network_dict['multicast'] = network.multicast
network_dict['status'] = None
else:
network_dict['private_net'] = None
network_dict['multicast'] = None
network_dict['status'] = network.status
return network_dict
def _create_network(self):
# Make sure service_plan argument is defined
if self.mcp_version == '2.0' and 'service_plan' not in self.module.params:
self.module.fail_json(
msg='service_plan required when creating network and location is MCP 2.0'
)
# Create network
try:
if self.mcp_version == '1.0':
network = self.driver.ex_create_network(
self.location,
self.name,
description=self.description
)
else:
network = self.driver.ex_create_network_domain(
self.location,
self.name,
self.module.params['service_plan'],
description=self.description
)
except DimensionDataAPIException as e:
self.module.fail_json(
msg="Failed to create new network: %s" % to_native(e), exception=traceback.format_exc()
)
if self.module.params['wait'] is True:
network = self._wait_for_network_state(network.id, 'NORMAL')
return network
def _delete_network(self, network):
try:
if self.mcp_version == '1.0':
deleted = self.driver.ex_delete_network(network)
else:
deleted = self.driver.ex_delete_network_domain(network)
if deleted:
self.module.exit_json(
changed=True,
msg="Deleted network with id %s" % network.id
)
self.module.fail_json(
"Unexpected failure deleting network with id %s" % network.id
)
except DimensionDataAPIException as e:
self.module.fail_json(
msg="Failed to delete network: %s" % to_native(e), exception=traceback.format_exc()
)
def _wait_for_network_state(self, net_id, state_to_wait_for):
try:
return self.driver.connection.wait_for_state(
state_to_wait_for,
self.driver.ex_get_network_domain,
self.module.params['wait_poll_interval'],
self.module.params['wait_time'],
net_id
)
except DimensionDataAPIException as e:
self.module.fail_json(
msg='Network did not reach % state in time: %s' % (state_to_wait_for, to_native(e)),
exception=traceback.format_exc()
)
def main():
module = DimensionDataNetworkModule()
if module.state == 'present':
module.state_present()
elif module.state == 'absent':
module.state_absent()
if __name__ == '__main__':
main()